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

Commit 77a1acc

Browse files
NotBobTheBuilderjeffbcross
authored andcommitted
feat(ngRoute): add method for changing url params
Add a $route#updateParams method for changing the current route parameters without having to build a URL and call $location#path. Useful for apps with a structure involving programmatically moving between pages on the current route, but with different :param values. Properties in the object passed to $route.updateParams() will be added to the location as queryParams if not contained within the route's path definition.
1 parent 56bd037 commit 77a1acc

File tree

2 files changed

+134
-2
lines changed

2 files changed

+134
-2
lines changed

src/ngRoute/route.js

+32-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
*/
1818
/* global -ngRouteModule */
1919
var ngRouteModule = angular.module('ngRoute', ['ng']).
20-
provider('$route', $RouteProvider);
20+
provider('$route', $RouteProvider),
21+
$routeMinErr = angular.$$minErr('ngRoute');
2122

2223
/**
2324
* @ngdoc provider
@@ -436,6 +437,36 @@ function $RouteProvider(){
436437
reload: function() {
437438
forceReload = true;
438439
$rootScope.$evalAsync(updateRoute);
440+
},
441+
442+
/**
443+
* @ngdoc method
444+
* @name $route#updateParams
445+
*
446+
* @description
447+
* Causes `$route` service to update the current URL, replacing
448+
* current route parameters with those specified in `newParams`.
449+
* Provided property names that match the route's path segment
450+
* definitions will be interpolated into the location's path, while
451+
* remaining properties will be treated as query params.
452+
*
453+
* @param {Object} newParams mapping of URL parameter names to values
454+
*/
455+
updateParams: function(newParams) {
456+
if (this.current && this.current.$$route) {
457+
var searchParams = {}, self=this;
458+
459+
angular.forEach(Object.keys(newParams), function(key) {
460+
if (!self.current.pathParams[key]) searchParams[key] = newParams[key];
461+
});
462+
463+
newParams = angular.extend({}, this.current.params, newParams);
464+
$location.path(interpolate(this.current.$$route.originalPath, newParams));
465+
$location.search(angular.extend({}, $location.search(), searchParams));
466+
}
467+
else {
468+
throw $routeMinErr('norout', 'Tried updating route when with no current route');
469+
}
439470
}
440471
};
441472

test/ngRoute/routeSpec.js

+102-1
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,6 @@ describe('$route', function() {
10461046
});
10471047
});
10481048

1049-
10501049
describe('reload', function() {
10511050

10521051
it('should reload even if reloadOnSearch is false', function() {
@@ -1078,4 +1077,106 @@ describe('$route', function() {
10781077
});
10791078
});
10801079
});
1080+
1081+
describe('update', function() {
1082+
it('should support single-parameter route updating', function() {
1083+
var routeChangeSpy = jasmine.createSpy('route change');
1084+
1085+
module(function($routeProvider) {
1086+
$routeProvider.when('/bar/:barId', {controller: angular.noop});
1087+
});
1088+
1089+
inject(function($route, $routeParams, $location, $rootScope) {
1090+
$rootScope.$on('$routeChangeSuccess', routeChangeSpy);
1091+
1092+
$location.path('/bar/1');
1093+
$rootScope.$digest();
1094+
routeChangeSpy.reset();
1095+
1096+
$route.updateParams({barId: '2'});
1097+
$rootScope.$digest();
1098+
1099+
expect($routeParams).toEqual({barId: '2'});
1100+
expect(routeChangeSpy).toHaveBeenCalledOnce();
1101+
expect($location.path()).toEqual('/bar/2');
1102+
});
1103+
});
1104+
1105+
it('should support total multi-parameter route updating', function() {
1106+
var routeChangeSpy = jasmine.createSpy('route change');
1107+
1108+
module(function($routeProvider) {
1109+
$routeProvider.when('/bar/:barId/:fooId/:spamId/:eggId', {controller: angular.noop});
1110+
});
1111+
1112+
inject(function($route, $routeParams, $location, $rootScope) {
1113+
$rootScope.$on('$routeChangeSuccess', routeChangeSpy);
1114+
1115+
$location.path('/bar/1/2/3/4');
1116+
$rootScope.$digest();
1117+
routeChangeSpy.reset();
1118+
1119+
$route.updateParams({barId: '5', fooId: '6', spamId: '7', eggId: '8'});
1120+
$rootScope.$digest();
1121+
1122+
expect($routeParams).toEqual({barId: '5', fooId: '6', spamId: '7', eggId: '8'});
1123+
expect(routeChangeSpy).toHaveBeenCalledOnce();
1124+
expect($location.path()).toEqual('/bar/5/6/7/8');
1125+
});
1126+
});
1127+
1128+
it('should support partial multi-parameter route updating', function() {
1129+
var routeChangeSpy = jasmine.createSpy('route change');
1130+
1131+
module(function($routeProvider) {
1132+
$routeProvider.when('/bar/:barId/:fooId/:spamId/:eggId', {controller: angular.noop});
1133+
});
1134+
1135+
inject(function($route, $routeParams, $location, $rootScope) {
1136+
$rootScope.$on('$routeChangeSuccess', routeChangeSpy);
1137+
1138+
$location.path('/bar/1/2/3/4');
1139+
$rootScope.$digest();
1140+
routeChangeSpy.reset();
1141+
1142+
$route.updateParams({barId: '5', fooId: '6'});
1143+
$rootScope.$digest();
1144+
1145+
expect($routeParams).toEqual({barId: '5', fooId: '6', spamId: '3', eggId: '4'});
1146+
expect(routeChangeSpy).toHaveBeenCalledOnce();
1147+
expect($location.path()).toEqual('/bar/5/6/3/4');
1148+
});
1149+
});
1150+
1151+
1152+
it('should update query params when new properties are not in path', function() {
1153+
var routeChangeSpy = jasmine.createSpy('route change');
1154+
1155+
module(function($routeProvider) {
1156+
$routeProvider.when('/bar/:barId/:fooId/:spamId/', {controller: angular.noop});
1157+
});
1158+
1159+
inject(function($route, $routeParams, $location, $rootScope) {
1160+
$rootScope.$on('$routeChangeSuccess', routeChangeSpy);
1161+
1162+
$location.path('/bar/1/2/3');
1163+
$location.search({initial: 'true'});
1164+
$rootScope.$digest();
1165+
routeChangeSpy.reset();
1166+
1167+
$route.updateParams({barId: '5', fooId: '6', eggId: '4'});
1168+
$rootScope.$digest();
1169+
1170+
expect($routeParams).toEqual({barId: '5', fooId: '6', spamId: '3', eggId: '4', initial: 'true'});
1171+
expect(routeChangeSpy).toHaveBeenCalledOnce();
1172+
expect($location.path()).toEqual('/bar/5/6/3/');
1173+
expect($location.search()).toEqual({eggId: '4', initial: 'true'});
1174+
});
1175+
});
1176+
1177+
1178+
it('should complain if called without an existing route', inject(function($route) {
1179+
expect($route.updateParams).toThrowMinErr('ngRoute', 'norout');
1180+
}));
1181+
});
10811182
});

0 commit comments

Comments
 (0)