mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-25 02:40:24 +00:00
274 lines
9 KiB
JavaScript
274 lines
9 KiB
JavaScript
'use strict';
|
|
|
|
ngRouteModule.directive('ngView', ngViewFactory);
|
|
ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|
|
|
|
|
/**
|
|
* @ngdoc directive
|
|
* @name ngRoute.directive:ngView
|
|
* @restrict ECA
|
|
*
|
|
* @description
|
|
* # Overview
|
|
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
|
|
* including the rendered template of the current route into the main layout (`index.html`) file.
|
|
* Every time the current route changes, the included view changes with it according to the
|
|
* configuration of the `$route` service.
|
|
*
|
|
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
|
*
|
|
* @animations
|
|
* enter - animation is used to bring new content into the browser.
|
|
* leave - animation is used to animate existing content away.
|
|
*
|
|
* The enter and leave animation occur concurrently.
|
|
*
|
|
* @scope
|
|
* @priority 400
|
|
* @param {string=} onload Expression to evaluate whenever the view updates.
|
|
*
|
|
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
|
|
* $anchorScroll} to scroll the viewport after the view is updated.
|
|
*
|
|
* - If the attribute is not set, disable scrolling.
|
|
* - If the attribute is set without value, enable scrolling.
|
|
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
|
|
* as an expression yields a truthy value.
|
|
* @example
|
|
<example module="ngViewExample" deps="angular-route.js" animations="true">
|
|
<file name="index.html">
|
|
<div ng-controller="MainCntl as main">
|
|
Choose:
|
|
<a href="Book/Moby">Moby</a> |
|
|
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
|
<a href="Book/Gatsby">Gatsby</a> |
|
|
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
|
|
<a href="Book/Scarlet">Scarlet Letter</a><br/>
|
|
|
|
<div class="view-animate-container">
|
|
<div ng-view class="view-animate"></div>
|
|
</div>
|
|
<hr />
|
|
|
|
<pre>$location.path() = {{main.$location.path()}}</pre>
|
|
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
|
|
<pre>$route.current.params = {{main.$route.current.params}}</pre>
|
|
<pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
|
|
<pre>$routeParams = {{main.$routeParams}}</pre>
|
|
</div>
|
|
</file>
|
|
|
|
<file name="book.html">
|
|
<div>
|
|
controller: {{book.name}}<br />
|
|
Book Id: {{book.params.bookId}}<br />
|
|
</div>
|
|
</file>
|
|
|
|
<file name="chapter.html">
|
|
<div>
|
|
controller: {{chapter.name}}<br />
|
|
Book Id: {{chapter.params.bookId}}<br />
|
|
Chapter Id: {{chapter.params.chapterId}}
|
|
</div>
|
|
</file>
|
|
|
|
<file name="animations.css">
|
|
.view-animate-container {
|
|
position:relative;
|
|
height:100px!important;
|
|
position:relative;
|
|
background:white;
|
|
border:1px solid black;
|
|
height:40px;
|
|
overflow:hidden;
|
|
}
|
|
|
|
.view-animate {
|
|
padding:10px;
|
|
}
|
|
|
|
.view-animate.ng-enter, .view-animate.ng-leave {
|
|
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
|
|
|
display:block;
|
|
width:100%;
|
|
border-left:1px solid black;
|
|
|
|
position:absolute;
|
|
top:0;
|
|
left:0;
|
|
right:0;
|
|
bottom:0;
|
|
padding:10px;
|
|
}
|
|
|
|
.view-animate.ng-enter {
|
|
left:100%;
|
|
}
|
|
.view-animate.ng-enter.ng-enter-active {
|
|
left:0;
|
|
}
|
|
.view-animate.ng-leave.ng-leave-active {
|
|
left:-100%;
|
|
}
|
|
</file>
|
|
|
|
<file name="script.js">
|
|
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'],
|
|
function($routeProvider, $locationProvider) {
|
|
$routeProvider.when('/Book/:bookId', {
|
|
templateUrl: 'book.html',
|
|
controller: BookCntl,
|
|
controllerAs: 'book'
|
|
});
|
|
$routeProvider.when('/Book/:bookId/ch/:chapterId', {
|
|
templateUrl: 'chapter.html',
|
|
controller: ChapterCntl,
|
|
controllerAs: 'chapter'
|
|
});
|
|
|
|
// configure html5 to get links working on jsfiddle
|
|
$locationProvider.html5Mode(true);
|
|
});
|
|
|
|
function MainCntl($route, $routeParams, $location) {
|
|
this.$route = $route;
|
|
this.$location = $location;
|
|
this.$routeParams = $routeParams;
|
|
}
|
|
|
|
function BookCntl($routeParams) {
|
|
this.name = "BookCntl";
|
|
this.params = $routeParams;
|
|
}
|
|
|
|
function ChapterCntl($routeParams) {
|
|
this.name = "ChapterCntl";
|
|
this.params = $routeParams;
|
|
}
|
|
</file>
|
|
|
|
<file name="scenario.js">
|
|
it('should load and compile correct template', function() {
|
|
element('a:contains("Moby: Ch1")').click();
|
|
var content = element('.doc-example-live [ng-view]').text();
|
|
expect(content).toMatch(/controller\: ChapterCntl/);
|
|
expect(content).toMatch(/Book Id\: Moby/);
|
|
expect(content).toMatch(/Chapter Id\: 1/);
|
|
|
|
element('a:contains("Scarlet")').click();
|
|
content = element('.doc-example-live [ng-view]').text();
|
|
expect(content).toMatch(/controller\: BookCntl/);
|
|
expect(content).toMatch(/Book Id\: Scarlet/);
|
|
});
|
|
</file>
|
|
</example>
|
|
*/
|
|
|
|
|
|
/**
|
|
* @ngdoc event
|
|
* @name ngRoute.directive:ngView#$viewContentLoaded
|
|
* @eventOf ngRoute.directive:ngView
|
|
* @eventType emit on the current ngView scope
|
|
* @description
|
|
* Emitted every time the ngView content is reloaded.
|
|
*/
|
|
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
|
|
function ngViewFactory( $route, $anchorScroll, $animate) {
|
|
return {
|
|
restrict: 'ECA',
|
|
terminal: true,
|
|
priority: 400,
|
|
transclude: 'element',
|
|
link: function(scope, $element, attr, ctrl, $transclude) {
|
|
var currentScope,
|
|
currentElement,
|
|
autoScrollExp = attr.autoscroll,
|
|
onloadExp = attr.onload || '';
|
|
|
|
scope.$on('$routeChangeSuccess', update);
|
|
update();
|
|
|
|
function cleanupLastView() {
|
|
if (currentScope) {
|
|
currentScope.$destroy();
|
|
currentScope = null;
|
|
}
|
|
if(currentElement) {
|
|
$animate.leave(currentElement);
|
|
currentElement = null;
|
|
}
|
|
}
|
|
|
|
function update() {
|
|
var locals = $route.current && $route.current.locals,
|
|
template = locals && locals.$template;
|
|
|
|
if (angular.isDefined(template)) {
|
|
var newScope = scope.$new();
|
|
var current = $route.current;
|
|
|
|
// Note: This will also link all children of ng-view that were contained in the original
|
|
// html. If that content contains controllers, ... they could pollute/change the scope.
|
|
// However, using ng-view on an element with additional content does not make sense...
|
|
// Note: We can't remove them in the cloneAttchFn of $transclude as that
|
|
// function is called before linking the content, which would apply child
|
|
// directives to non existing elements.
|
|
var clone = $transclude(newScope, function(clone) {
|
|
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
|
if (angular.isDefined(autoScrollExp)
|
|
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
|
$anchorScroll();
|
|
}
|
|
});
|
|
cleanupLastView();
|
|
});
|
|
|
|
currentElement = clone;
|
|
currentScope = current.scope = newScope;
|
|
currentScope.$emit('$viewContentLoaded');
|
|
currentScope.$eval(onloadExp);
|
|
} else {
|
|
cleanupLastView();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// This directive is called during the $transclude call of the first `ngView` directive.
|
|
// It will replace and compile the content of the element with the loaded template.
|
|
// We need this directive so that the element content is already filled when
|
|
// the link function of another directive on the same element as ngView
|
|
// is called.
|
|
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
|
|
function ngViewFillContentFactory($compile, $controller, $route) {
|
|
return {
|
|
restrict: 'ECA',
|
|
priority: -400,
|
|
link: function(scope, $element) {
|
|
var current = $route.current,
|
|
locals = current.locals;
|
|
|
|
$element.html(locals.$template);
|
|
|
|
var link = $compile($element.contents());
|
|
|
|
if (current.controller) {
|
|
locals.$scope = scope;
|
|
var controller = $controller(current.controller, locals);
|
|
if (current.controllerAs) {
|
|
scope[current.controllerAs] = controller;
|
|
}
|
|
$element.data('$ngControllerController', controller);
|
|
$element.children().data('$ngControllerController', controller);
|
|
}
|
|
|
|
link(scope);
|
|
}
|
|
};
|
|
}
|