diff --git a/src/service/route.js b/src/service/route.js index 97c9cee00ea5..5dee031c99e2 100644 --- a/src/service/route.js +++ b/src/service/route.js @@ -75,6 +75,7 @@ function $RouteProvider(){ * * @param {Route} next Future route information. * @param {Route} current Current route information. + * @param {Function} function which stops route change and reverts location to previous state. * * The `Route` object extends the route definition with the following properties. * @@ -117,6 +118,7 @@ function $RouteProvider(){ parentScope = $rootScope, dirty = 0, forceReload = false, + stopUpdateUrl, $route = { routes: routes, @@ -221,7 +223,7 @@ function $RouteProvider(){ } }; - $rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute); + $rootScope.$watch(function() { return {dirty: dirty, url: $location.url()}; }, updateRoute); return $route; @@ -251,7 +253,22 @@ function $RouteProvider(){ return match ? dst : null; } - function updateRoute() { + function disableUpdate(backUrl) { + stopUpdateUrl = backUrl; + $location.url(backUrl); + } + + function enableUpdate(newUrl) { + if(equals(newUrl, stopUpdateUrl)){ + stopUpdateUrl = undefined; + } + } + + function isUpdateStopped(){ + return !!stopUpdateUrl; + } + + function updateRoute(scope, newValue, oldValue) { var next = parseRoute(), last = $route.current, Controller; @@ -263,7 +280,15 @@ function $RouteProvider(){ last.scope && last.scope.$emit('$routeUpdate'); } else { forceReload = false; - $rootScope.$broadcast('$beforeRouteChange', next, last); + if(!isUpdateStopped()) { + $rootScope.$broadcast('$beforeRouteChange', next, last, function(){ + disableUpdate(oldValue.url); + }); + } + if(isUpdateStopped()) { + enableUpdate(newValue.url); + return; + } last && last.scope && last.scope.$destroy(); $route.current = next; if (next) { diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js index fed3faef363d..90de5251fd2d 100644 --- a/test/service/routeSpec.js +++ b/test/service/routeSpec.js @@ -48,6 +48,20 @@ describe('$route', function() { $route.when('/NONE', {template:'instant update'}); $rootScope.$digest(); expect($route.current.template).toEqual('instant update'); + + var lastPath = $location.path(); + var lastSearch = $location.search(); + + log = ''; + $rootScope.$on('$beforeRouteChange', function(event, next, current, stopCallback) { + log += 'stop();'; + stopCallback(); + }); + $location.path('/Book/Moby2/Chapter/Intro2').search('p=1234'); + $rootScope.$digest(); + expect(log).toEqual('before();stop();'); + expect($location.path()).toEqual(lastPath); + expect($location.search()).toEqual(lastSearch); }));