diff --git a/src/urlRouter.js b/src/urlRouter.js index 46dd1deaf..6bc0ac89a 100644 --- a/src/urlRouter.js +++ b/src/urlRouter.js @@ -92,7 +92,8 @@ function $UrlRouterProvider( $urlMatcherFactory) { [ '$location', '$rootScope', '$injector', function ($location, $rootScope, $injector) { // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree - function update() { + function update(evt) { + if (evt && evt.defaultPrevented) return; function check(rule) { var handled = rule($injector, $location); if (handled) { @@ -110,7 +111,12 @@ function $UrlRouterProvider( $urlMatcherFactory) { } $rootScope.$on('$locationChangeSuccess', update); - return {}; + + return { + sync: function () { + update(); + } + }; }]; } diff --git a/test/urlRouterSpec.js b/test/urlRouterSpec.js index 7509c655a..c0cc24fcd 100644 --- a/test/urlRouterSpec.js +++ b/test/urlRouterSpec.js @@ -80,6 +80,32 @@ describe("UrlRouter", function () { expect(custom.url.format).not.toHaveBeenCalled(); expect(custom.handler).toHaveBeenCalled(); }); + + it('can be cancelled by preventDefault() in $locationChangeSuccess', inject(function () { + var called; + location.path("/baz"); + scope.$on('$locationChangeSuccess', function (ev) { + ev.preventDefault(); + called = true; + }); + scope.$emit("$locationChangeSuccess"); + expect(called).toBeTruthy(); + expect(location.path()).toBe("/baz"); + })); + + it('can be deferred and updated in $locationChangeSuccess', inject(function ($urlRouter, $timeout) { + var called; + location.path("/baz"); + scope.$on('$locationChangeSuccess', function (ev) { + ev.preventDefault(); + called = true; + $timeout($urlRouter.sync, 2000); + }); + scope.$emit("$locationChangeSuccess"); + $timeout.flush(); + expect(called).toBeTruthy(); + expect(location.path()).toBe("/b4z"); + })); }); }); \ No newline at end of file