Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 3f8b285

Browse files
committed
fix(ngRoute): allow ngView to be included in an asynchronously loaded template
During it's linking phase, `ngView` relies on the info provided in `$route.current` for instantiating the initial view. `$route.current` is set in the callback of a listener to `$locationChangeSuccess`, which is registered during the instantiation of the `$route` service. Thus, it is crucial that the `$route` service is instantiated before the initial `$locationChangeSuccess` is fired. Since `ngView` declares `$route` as a dependency, the service is instantiated in time if `ngView` is present during the initial load of the page. Yet, in cases where `ngView` is included in a template that is loaded asynchronously (e.g. in another directive's template), the directive factory might not be called soon enough for `$route` to be instantiated before the initial `$locationChangeSuccess` event is fired. This commit fixes it, by always instantiating `$route` up front, during the initialization phase. Fixes #1213 Fixes #6812
1 parent 2d6c218 commit 3f8b285

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

Diff for: src/ngRoute/route.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
*/
1818
/* global -ngRouteModule */
1919
var ngRouteModule = angular.module('ngRoute', ['ng']).
20-
provider('$route', $RouteProvider),
20+
provider('$route', $RouteProvider).
21+
// Ensure `$route` will be instantiated in time to capture the initial
22+
// `$locationChangeSuccess` event. This is necessary in case `ngView` is
23+
// included in an asynchronously loaded template.
24+
run(['$route', angular.noop]),
2125
$routeMinErr = angular.$$minErr('ngRoute');
2226

2327
/**

Diff for: test/ngRoute/directive/ngViewSpec.js

+31
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,34 @@ describe('ngView animations', function() {
10271027
));
10281028
});
10291029
});
1030+
1031+
describe('ngView in async template', function() {
1032+
beforeEach(module('ngRoute'));
1033+
beforeEach(module(function($compileProvider, $provide, $routeProvider) {
1034+
$compileProvider.directive('asyncView', function() {
1035+
return {templateUrl: 'async-view.html'};
1036+
});
1037+
1038+
$provide.decorator('$templateRequest', function($timeout) {
1039+
return function() {
1040+
return $timeout(angular.identity, 500, false, '<ng-view></ng-view>');
1041+
};
1042+
});
1043+
1044+
$routeProvider.when('/', {template: 'Hello, world !'});
1045+
}));
1046+
1047+
1048+
it('should work correctly upon initial page load',
1049+
// Injecting `$location` here is necessary, so that it gets instantiated early
1050+
inject(function($compile, $location, $rootScope, $timeout) {
1051+
var elem = $compile('<async-view></async-view>')($rootScope);
1052+
$rootScope.$digest();
1053+
$timeout.flush(500);
1054+
1055+
expect(elem.text()).toBe('Hello, world !');
1056+
1057+
dealoc(elem);
1058+
})
1059+
);
1060+
});

Diff for: test/ngRoute/routeSpec.js

+15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ describe('$route', function() {
2323
dealoc(element);
2424
});
2525

26+
it('should be loaded upon initial load (even if `ngView` is loaded async)', function() {
27+
module(function($routeProvider) {
28+
$routeProvider.when('/', {template: 'Hello, world !'});
29+
});
30+
31+
inject(function($location, $rootScope) {
32+
$location.path('/');
33+
$rootScope.$digest();
34+
});
35+
36+
inject(function($route) {
37+
expect($route.current).toBeDefined();
38+
});
39+
});
40+
2641
it('should allow cancellation via $locationChangeStart via $routeChangeStart', function() {
2742
module(function($routeProvider) {
2843
$routeProvider.when('/Edit', {

0 commit comments

Comments
 (0)