aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Minar2011-02-07 14:32:28 -0800
committerIgor Minar2011-02-07 23:56:33 -0800
commit86321d1f5722e0aefcdbe8f3e5a14bd15d4caecb (patch)
treef4375a0af8af9da94878214f3c24ad33d7ed97f4
parent8724e97b7e6638797d3607a45682ef0b76311aae (diff)
downloadangular.js-86321d1f5722e0aefcdbe8f3e5a14bd15d4caecb.tar.bz2
add support for hashSearch redirection and custom redirection functions
-rw-r--r--src/services.js59
-rw-r--r--test/servicesSpec.js43
2 files changed, 75 insertions, 27 deletions
diff --git a/src/services.js b/src/services.js
index 9dfdd35e..be5189d1 100644
--- a/src/services.js
+++ b/src/services.js
@@ -748,13 +748,23 @@ angularServiceInject('$route', function(location, $updateView) {
* Object properties:
*
* - `controller` – `{function()=}` – Controller fn that should be associated with newly
- * created scope.
+ * created scope.
* - `template` – `{string=}` – path to an html template that should be used by
- * {@link angular.widget.ng:view ng:view} or
- * {@link angular.widget.ng:include ng:include} widgets.
- * - `redirectTo` – {string=} – value to update
- * {@link angular.service.$location $location} hash with and trigger route
- * redirection.
+ * {@link angular.widget.ng:view ng:view} or
+ * {@link angular.widget.ng:include ng:include} widgets.
+ * - `redirectTo` – {(string|function())=} – value to update
+ * {@link angular.service.$location $location} hash with and trigger route redirection.
+ *
+ * If `redirectTo` is a function, it will be called with the following parameters:
+ *
+ * - `{Object.<string>}` - route parameters extracted from the current
+ * `$location.hashPath` by applying the current route template.
+ * - `{string}` - current `$location.hash`
+ * - `{string}` - current `$location.hashPath`
+ * - `{string}` - current `$location.hashSearch`
+ *
+ * The custom `redirectTo` function is expected to return a string which will be used
+ * to update `$location.hash`.
*
* @returns {Object} route object
*
@@ -801,7 +811,7 @@ angularServiceInject('$route', function(location, $updateView) {
}
};
function updateRoute(){
- var childScope, routeParams, pathParams, redirectPath, segmentMatch, key;
+ var childScope, routeParams, pathParams, segmentMatch, key, redir;
$route.current = _null;
forEach(routes, function(rParams, rPath) {
@@ -817,18 +827,29 @@ angularServiceInject('$route', function(location, $updateView) {
if(routeParams) {
if (routeParams.redirectTo) {
- redirectPath = '';
- forEach(routeParams.redirectTo.split(':'), function(segment, i) {
- if (i==0) {
- redirectPath += segment;
- } else {
- segmentMatch = segment.match(/(\w+)(.*)/);
- key = segmentMatch[1];
- redirectPath += pathParams[key] || location.hashSearch[key];
- redirectPath += segmentMatch[2] || '';
- }
- });
- location.updateHash(redirectPath);
+ if (isString(routeParams.redirectTo)) {
+ // interpolate the redirectTo string
+ redir = {hashPath: '',
+ hashSearch: extend({}, location.hashSearch, pathParams)};
+
+ forEach(routeParams.redirectTo.split(':'), function(segment, i) {
+ if (i==0) {
+ redir.hashPath += segment;
+ } else {
+ segmentMatch = segment.match(/(\w+)(.*)/);
+ key = segmentMatch[1];
+ redir.hashPath += pathParams[key] || location.hashSearch[key];
+ redir.hashPath += segmentMatch[2] || '';
+ delete redir.hashSearch[key];
+ }
+ });
+ } else {
+ // call custom redirectTo function
+ redir = {hash: routeParams.redirectTo(pathParams, location.hash, location.hashPath,
+ location.hashSearch)};
+ }
+
+ location.update(redir);
$updateView(); //TODO this is to work around the $location<=>$browser issues
return;
}
diff --git a/test/servicesSpec.js b/test/servicesSpec.js
index 637f767c..0186684e 100644
--- a/test/servicesSpec.js
+++ b/test/servicesSpec.js
@@ -523,14 +523,14 @@ describe("service", function(){
expect(onChangeSpy.callCount).toBe(1);
});
-
- it('should interpolate route variables in the redirected path from hashPath', function() {
+ it('should interpolate route variables in the redirected hashPath from the original hashPath',
+ function() {
var scope = angular.scope(),
$location = scope.$service('$location'),
$browser = scope.$service('$browser'),
$route = scope.$service('$route');
- $route.when('/foo/:id/foo/:subid/:ignoredId', {redirectTo: '/bar/:id/:subid/23'});
+ $route.when('/foo/:id/foo/:subid/:extraId', {redirectTo: '/bar/:id/:subid/23'});
$route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'});
scope.$eval();
@@ -538,27 +538,54 @@ describe("service", function(){
scope.$eval(); //triggers initial route change - match the redirect route
$browser.defer.flush(); //triger route change - match the route we redirected to
- expect($location.hash).toBe('/bar/id1/subid3/23');
+ expect($location.hash).toBe('/bar/id1/subid3/23?extraId=gah');
expect($route.current.template).toBe('bar.html');
});
- it('should interpolate route variables in the redirected path from hashSearch', function() {
+ it('should interpolate route variables in the redirected hashPath from the original hashSearch',
+ function() {
var scope = angular.scope(),
$location = scope.$service('$location'),
$browser = scope.$service('$browser'),
$route = scope.$service('$route');
$route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'});
- $route.when('/foo/:id', {redirectTo: '/bar/:id/:subid/99'});
+ $route.when('/foo/:id/:extra', {redirectTo: '/bar/:id/:subid/99'});
scope.$eval();
- $location.hash = '/foo/id3?subid=sid1&ignored=true';
+ $location.hash = '/foo/id3/eId?subid=sid1&appended=true';
scope.$eval(); //triggers initial route change - match the redirect route
$browser.defer.flush(); //triger route change - match the route we redirected to
- expect($location.hash).toBe('/bar/id3/sid1/99');
+ expect($location.hash).toBe('/bar/id3/sid1/99?appended=true&extra=eId');
expect($route.current.template).toBe('bar.html');
});
+
+ it('should allow custom redirectTo function to be used', function() {
+ var scope = angular.scope(),
+ $location = scope.$service('$location'),
+ $browser = scope.$service('$browser'),
+ $route = scope.$service('$route');
+
+ $route.when('/bar/:id/:subid/:subsubid', {template: 'bar.html'});
+ $route.when('/foo/:id',
+ {redirectTo: customRedirectFn});
+ scope.$eval();
+
+ $location.hash = '/foo/id3?subid=sid1&appended=true';
+ scope.$eval(); //triggers initial route change - match the redirect route
+ $browser.defer.flush(); //triger route change - match the route we redirected to
+
+ expect($location.hash).toBe('custom');
+
+ function customRedirectFn(routePathParams, hash, hashPath, hashSearch) {
+ expect(routePathParams).toEqual({id: 'id3'});
+ expect(hash).toEqual($location.hash);
+ expect(hashPath).toEqual($location.hashPath);
+ expect(hashSearch).toEqual($location.hashSearch);
+ return 'custom';
+ }
+ });
});