angular.js/src/ngRoute/directive/ngView.js
Igor Minar 5599b55b04 refactor($route): pull $route and friends into angular-route.js
$route, $routeParams and ngView have been pulled from core angular.js
to angular-route.js/ngRoute module.

This is was done to in order keep the core focused on most commonly
used functionality and allow community routers to be freely used
instead of $route service.

There is no need to panic, angular-route will keep on being supported
by the angular team.

Note: I'm intentionally not fixing tutorial links. Tutorial will need
bigger changes and those should be done when we update tutorial to
1.2.

BREAKING CHANGE: applications that use $route will now need to load
angular-route.js file and define dependency on ngRoute module.

Before:

```
...
<script src="angular.js"></script>
...
var myApp = angular.module('myApp', ['someOtherModule']);
...
```

After:

```
...
<script src="angular.js"></script>
<script src="angular-route.js"></script>
...
var myApp = angular.module('myApp', ['ngRoute', 'someOtherModule']);
...
```

Closes #2804
2013-06-06 17:07:12 -07:00

226 lines
7 KiB
JavaScript

'use strict';
ngRouteModule.directive('ngView', ngViewFactory);
/**
* @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.
*
* Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter**
* and **leave** effects.
*
* @animations
* enter - happens just after the ngView contents are changed (when the new view DOM element is inserted into the DOM)
* leave - happens just after the current ngView contents change and just before the former contents are removed from the DOM
*
* @scope
* @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
ng-view
class="example-animate-container"
ng-animate="{enter: 'example-enter', leave: 'example-leave'}"></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">
.example-leave, .example-enter {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-o-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;
}
.example-animate-container {
position:relative;
height:100px;
}
.example-animate-container > * {
display:block;
width:100%;
border-left:1px solid black;
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
padding:10px;
}
.example-enter {
left:100%;
}
.example-enter.example-enter-active {
left:0;
}
.example-leave { }
.example-leave.example-leave-active {
left:-100%;
}
</file>
<file name="script.js">
angular.module('ngViewExample', ['ngRoute'], 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', '$compile', '$controller', '$animator'];
function ngViewFactory( $route, $anchorScroll, $compile, $controller, $animator) {
return {
restrict: 'ECA',
terminal: true,
link: function(scope, element, attr) {
var lastScope,
onloadExp = attr.onload || '',
animate = $animator(scope, attr);
scope.$on('$routeChangeSuccess', update);
update();
function destroyLastScope() {
if (lastScope) {
lastScope.$destroy();
lastScope = null;
}
}
function clearContent() {
animate.leave(element.contents(), element);
destroyLastScope();
}
function update() {
var locals = $route.current && $route.current.locals,
template = locals && locals.$template;
if (template) {
clearContent();
var enterElements = jqLite('<div></div>').html(template).contents();
animate.enter(enterElements, element);
var link = $compile(enterElements),
current = $route.current,
controller;
lastScope = current.scope = scope.$new();
if (current.controller) {
locals.$scope = lastScope;
controller = $controller(current.controller, locals);
if (current.controllerAs) {
lastScope[current.controllerAs] = controller;
}
element.children().data('$ngControllerController', controller);
}
link(lastScope);
lastScope.$emit('$viewContentLoaded');
lastScope.$eval(onloadExp);
// $anchorScroll might listen on event...
$anchorScroll();
} else {
clearContent();
}
}
}
};
}