Skip to content

Commit 0206de7

Browse files
fix($route): don't process route change controllers and templates for redirectTo routes
If a route defines a `redirectTo` value, the current route should stop processing the route and instead wait to process the route of the redirect. Currently, what is happening is that Angular detects a redirectTo value and updates $location, but then continues processing the route that was intended to be redirected. Templates are loaded, resolves are processed, ng-view then updates the view with a new template and instantiates the controller all for a route that should have been redirected. A common use case for assigning a function to the redirectTo is to validation authentication, permission check, or some other logic to determine if the route should continue or redirect else where. In the end, this happens, but in between, unexpected results may occur by updating the view and instantiating controllers for logic that wasn't expected to be executed. http://plnkr.co/edit/8QlA0ouuePH3p35Ntmjy?p=preview This commit checks for a url change after a potential redirect, it the url changed, and is not `null` nor `undefined`, exit out and don't process current route change. Closes angular#3332 BREAKING CHANGE The $route service no longer instantiates controllers nor calls resolves or template functions for routes that have a `redirectTo` unless the `redirectTo` is a function that returns `undefined`.
1 parent 7db30b1 commit 0206de7

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/ngRoute/route.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ function $RouteProvider() {
136136
* The custom `redirectTo` function is expected to return a string which will be used
137137
* to update `$location.path()` and `$location.search()`.
138138
*
139+
* Routes that specify `redirectTo` will not have their controllers, template functions
140+
* or resolves called, the `$location` will be changed to the redirect url and route
141+
* processing will stop. The exception to this is if the `redirectTo` is a function that
142+
* returns `undefined`. In this case the route transition occurs as though their was no
143+
* redirection.
144+
*
139145
* - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()`
140146
* or `$location.hash()` changes.
141147
*
@@ -599,7 +605,7 @@ function $RouteProvider() {
599605
newUrl = nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search());
600606
$location.url(newUrl).replace();
601607
}
602-
if (isDefined(newUrl) && url !== newUrl) {
608+
if (angular.isDefined(newUrl) && url !== newUrl) {
603609
return; //exit out and don't process current next value, wait for next location change from redirect
604610
}
605611
}

test/ngRoute/routeSpec.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
fdescribe('$route', function() {
3+
describe('$route', function() {
44
var $httpBackend,
55
element;
66

@@ -1062,30 +1062,39 @@ fdescribe('$route', function() {
10621062
});
10631063
});
10641064

1065-
it('should not instantiate controller or process template for a redirected route', function() {
1065+
it('should not process route bits', function() {
10661066
var firstController = jasmine.createSpy('first controller spy');
10671067
var firstTemplate = jasmine.createSpy('first template spy').and.returnValue('redirected view');
1068+
var firstResolve = jasmine.createSpy('first resolve spy');
10681069
var secondController = jasmine.createSpy('second controller spy');
10691070
var secondTemplate = jasmine.createSpy('second template spy').and.returnValue('redirected view');
1071+
var secondResolve = jasmine.createSpy('second resolve spy');
10701072
module(function($routeProvider) {
10711073
$routeProvider.when('/redirect', {
10721074
template: firstTemplate,
10731075
redirectTo: '/redirected',
1076+
resolve: { value: firstResolve },
10741077
controller: firstController
10751078
});
10761079
$routeProvider.when('/redirected', {
10771080
template: secondTemplate,
1081+
resolve: { value: secondResolve },
10781082
controller: secondController
10791083
});
10801084
});
10811085
inject(function($route, $location, $rootScope, $compile) {
10821086
var element = $compile('<div><ng-view></ng-view></div>')($rootScope);
10831087
$location.path('/redirect');
10841088
$rootScope.$digest();
1089+
10851090
expect(firstController).not.toHaveBeenCalled();
10861091
expect(firstTemplate).not.toHaveBeenCalled();
1092+
expect(firstResolve).not.toHaveBeenCalled();
1093+
10871094
expect(secondController).toHaveBeenCalled();
10881095
expect(secondTemplate).toHaveBeenCalled();
1096+
expect(secondResolve).toHaveBeenCalled();
1097+
10891098
dealoc(element);
10901099
});
10911100
});

0 commit comments

Comments
 (0)