diff options
| author | Igor Minar | 2011-02-07 14:32:28 -0800 | 
|---|---|---|
| committer | Igor Minar | 2011-02-07 23:56:33 -0800 | 
| commit | 86321d1f5722e0aefcdbe8f3e5a14bd15d4caecb (patch) | |
| tree | f4375a0af8af9da94878214f3c24ad33d7ed97f4 | |
| parent | 8724e97b7e6638797d3607a45682ef0b76311aae (diff) | |
| download | angular.js-86321d1f5722e0aefcdbe8f3e5a14bd15d4caecb.tar.bz2 | |
add support for hashSearch redirection and custom redirection functions
| -rw-r--r-- | src/services.js | 59 | ||||
| -rw-r--r-- | test/servicesSpec.js | 43 | 
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'; +      } +    });    }); | 
