aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/service/route.js36
-rw-r--r--test/service/routeSpec.js135
2 files changed, 165 insertions, 6 deletions
diff --git a/src/service/route.js b/src/service/route.js
index 972d616e..b7e4814b 100644
--- a/src/service/route.js
+++ b/src/service/route.js
@@ -68,6 +68,8 @@ angularServiceInject('$route', function($location) {
matcher = switchRouteMatcher,
parentScope = this,
dirty = 0,
+ lastHashPath,
+ lastRouteParams,
$route = {
routes: routes,
@@ -136,6 +138,18 @@ angularServiceInject('$route', function($location) {
* The custom `redirectTo` function is expected to return a string which will be used
* to update `$location.hash`.
*
+ * - `[reloadOnSearch=true]` - {boolean=} - reload route when $location.hashSearch
+ * changes. If this option is disabled, you should set up a $watch to be notified of
+ * param (hashSearch) changes as follows:
+ *
+ * function MyCtrl($route) {
+ * this.$watch(function() {
+ * return $route.current.params;
+ * }, function(scope, params) {
+ * //do stuff with params
+ * });
+ * }
+ *
* @returns {Object} route object
*
* @description
@@ -144,8 +158,8 @@ angularServiceInject('$route', function($location) {
when:function (path, params) {
if (isUndefined(path)) return routes; //TODO(im): remove - not needed!
var route = routes[path];
- if (!route) route = routes[path] = {};
- if (params) extend(route, params);
+ if (!route) route = routes[path] = {reloadOnSearch: true};
+ if (params) extend(route, params); //TODO(im): what the heck? merge two route definitions?
dirty++;
return route;
},
@@ -209,9 +223,18 @@ angularServiceInject('$route', function($location) {
function updateRoute(){
var selectedRoute, pathParams, segmentMatch, key, redir;
- if ($route.current && $route.current.scope) {
- $route.current.scope.$destroy();
+ if ($route.current) {
+ if (!$route.current.reloadOnSearch && (lastHashPath == $location.hashPath)) {
+ $route.current.params = extend($location.hashSearch, lastRouteParams);
+ return;
+ }
+
+ if ($route.current.scope) {
+ $route.current.scope.$destroy();
+ }
}
+
+ lastHashPath = $location.hashPath;
$route.current = null;
// Match a route
forEach(routes, function(rParams, rPath) {
@@ -255,19 +278,20 @@ angularServiceInject('$route', function($location) {
$route.current = extend({}, selectedRoute);
$route.current.params = extend({}, $location.hashSearch, pathParams);
+ lastRouteParams = pathParams;
}
//fire onChange callbacks
forEach(onChange, parentScope.$eval, parentScope);
- // Create the scope if we have mtched a route
+ // Create the scope if we have matched a route
if ($route.current) {
$route.current.scope = parentScope.$new($route.current.controller);
}
}
- this.$watch(function(){return dirty + $location.hash;}, updateRoute);
+ this.$watch(function(){ return dirty + $location.hash; }, updateRoute);
return $route;
}, ['$location']);
diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js
index bfe201d1..72c7745c 100644
--- a/test/service/routeSpec.js
+++ b/test/service/routeSpec.js
@@ -260,4 +260,139 @@ describe('$route', function() {
}
});
});
+
+
+ describe('reloadOnSearch', function() {
+ it('should reload a route when reloadOnSearch is enabled and hashSearch changes', function() {
+ var scope = angular.scope(),
+ $location = scope.$service('$location'),
+ $route = scope.$service('$route'),
+ reloaded = jasmine.createSpy('route reload');
+
+ $route.when('/foo', {controller: FooCtrl});
+ $route.onChange(reloaded);
+
+ function FooCtrl() {
+ reloaded();
+ }
+
+ $location.updateHash('/foo');
+ scope.$digest();
+ expect(reloaded).toHaveBeenCalled();
+ reloaded.reset();
+
+ // trigger reload
+ $location.hashSearch.foo = 'bar';
+ scope.$digest();
+ expect(reloaded).toHaveBeenCalled();
+ });
+
+
+ it('should not reload a route when reloadOnSearch is disabled and only hashSearch changes',
+ function() {
+ var scope = angular.scope(),
+ $location = scope.$service('$location'),
+ $route = scope.$service('$route'),
+ reloaded = jasmine.createSpy('route reload');
+
+ $route.when('/foo', {controller: FooCtrl, reloadOnSearch: false});
+ $route.onChange(reloaded);
+
+ function FooCtrl() {
+ reloaded();
+ }
+
+ expect(reloaded).not.toHaveBeenCalled();
+
+ $location.updateHash('/foo');
+ scope.$digest();
+ expect(reloaded).toHaveBeenCalled();
+ reloaded.reset();
+
+ // don't trigger reload
+ $location.hashSearch.foo = 'bar';
+ scope.$digest();
+ expect(reloaded).not.toHaveBeenCalled();
+ });
+
+
+ it('should reload reloadOnSearch route when url differs only in route path param', function() {
+ var scope = angular.scope(),
+ $location = scope.$service('$location'),
+ $route = scope.$service('$route'),
+ reloaded = jasmine.createSpy('routeReload'),
+ onRouteChange = jasmine.createSpy('onRouteChange');
+
+ $route.when('/foo/:fooId', {controller: FooCtrl, reloadOnSearch: false});
+ $route.onChange(onRouteChange);
+
+ function FooCtrl() {
+ reloaded();
+ }
+
+ expect(reloaded).not.toHaveBeenCalled();
+ expect(onRouteChange).not.toHaveBeenCalled();
+
+ $location.updateHash('/foo/aaa');
+ scope.$digest();
+ expect(reloaded).toHaveBeenCalled();
+ expect(onRouteChange).toHaveBeenCalled();
+ reloaded.reset();
+ onRouteChange.reset();
+
+ $location.updateHash('/foo/bbb');
+ scope.$digest();
+ expect(reloaded).toHaveBeenCalled();
+ expect(onRouteChange).toHaveBeenCalled();
+ reloaded.reset();
+ onRouteChange.reset();
+
+ $location.hashSearch.foo = 'bar';
+ scope.$digest();
+ expect(reloaded).not.toHaveBeenCalled();
+ expect(onRouteChange).not.toHaveBeenCalled();
+ });
+
+
+ it('should update route params when reloadOnSearch is disabled and hashSearch', function() {
+ var scope = angular.scope(),
+ $location = scope.$service('$location'),
+ $route = scope.$service('$route'),
+ routeParams = jasmine.createSpy('routeParams');
+
+ $route.when('/foo', {controller: FooCtrl});
+ $route.when('/bar/:barId', {controller: FooCtrl, reloadOnSearch: false});
+
+ function FooCtrl() {
+ this.$watch(function() {
+ return $route.current.params;
+ }, function(scope, value) {
+ routeParams(value);
+ });
+ }
+
+ expect(routeParams).not.toHaveBeenCalled();
+
+ $location.updateHash('/foo');
+ scope.$digest();
+ expect(routeParams).toHaveBeenCalledWith({});
+ routeParams.reset();
+
+ // trigger reload
+ $location.hashSearch.foo = 'bar';
+ scope.$digest();
+ expect(routeParams).toHaveBeenCalledWith({foo: 'bar'});
+ routeParams.reset();
+
+ $location.updateHash('/bar/123');
+ scope.$digest();
+ expect(routeParams).toHaveBeenCalledWith({barId: '123'});
+ routeParams.reset();
+
+ // don't trigger reload
+ $location.hashSearch.foo = 'bar';
+ scope.$digest();
+ expect(routeParams).toHaveBeenCalledWith({barId: '123', foo: 'bar'});
+ });
+ });
});