mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-14 17:53:11 +00:00
feat(routeProvider): Add support to catch-all parameters in routes
This allows routeProvider to accept parameters that matches substrings even when they contain slashes if they are prefixed with an asterisk instead of a colon. For example, routes like edit/color/:color/largecode/*largecode will match with something like this http://appdomain.com/edit/color/brown/largecode/code/with/slashs.
This commit is contained in:
parent
bb8448c011
commit
7eafbb98c6
2 changed files with 80 additions and 7 deletions
|
|
@ -23,9 +23,18 @@ function $RouteProvider(){
|
||||||
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
||||||
* route definition.
|
* route definition.
|
||||||
*
|
*
|
||||||
* `path` can contain named groups starting with a colon (`:name`). All characters up to the
|
* * `path` can contain named groups starting with a colon (`:name`). All characters up
|
||||||
* next slash are matched and stored in `$routeParams` under the given `name` when the route
|
* to the next slash are matched and stored in `$routeParams` under the given `name`
|
||||||
* matches.
|
* when the route matches.
|
||||||
|
* * `path` can contain named groups starting with a star (`*name`). All characters are
|
||||||
|
* eagerly stored in `$routeParams` under the given `name` when the route matches.
|
||||||
|
*
|
||||||
|
* For example, routes like `/color/:color/largecode/*largecode/edit` will match
|
||||||
|
* `/color/brown/largecode/code/with/slashs/edit` and extract:
|
||||||
|
*
|
||||||
|
* * `color: brown`
|
||||||
|
* * `largecode: code/with/slashs`.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* @param {Object} route Mapping information to be assigned to `$route.current` on route
|
* @param {Object} route Mapping information to be assigned to `$route.current` on route
|
||||||
* match.
|
* match.
|
||||||
|
|
@ -341,12 +350,12 @@ function $RouteProvider(){
|
||||||
// regex only once and then reuse it
|
// regex only once and then reuse it
|
||||||
|
|
||||||
// Escape regexp special characters.
|
// Escape regexp special characters.
|
||||||
when = '^' + when.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + '$';
|
when = '^' + when.replace(/[-\/\\^$:*+?.()|[\]{}]/g, "\\$&") + '$';
|
||||||
var regex = '',
|
var regex = '',
|
||||||
params = [],
|
params = [],
|
||||||
dst = {};
|
dst = {};
|
||||||
|
|
||||||
var re = /:(\w+)/g,
|
var re = /\\([:*])(\w+)/g,
|
||||||
paramMatch,
|
paramMatch,
|
||||||
lastMatchedIndex = 0;
|
lastMatchedIndex = 0;
|
||||||
|
|
||||||
|
|
@ -354,8 +363,15 @@ function $RouteProvider(){
|
||||||
// Find each :param in `when` and replace it with a capturing group.
|
// Find each :param in `when` and replace it with a capturing group.
|
||||||
// Append all other sections of when unchanged.
|
// Append all other sections of when unchanged.
|
||||||
regex += when.slice(lastMatchedIndex, paramMatch.index);
|
regex += when.slice(lastMatchedIndex, paramMatch.index);
|
||||||
regex += '([^\\/]*)';
|
switch(paramMatch[1]) {
|
||||||
params.push(paramMatch[1]);
|
case ':':
|
||||||
|
regex += '([^\\/]*)';
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
regex += '(.*)';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
params.push(paramMatch[2]);
|
||||||
lastMatchedIndex = re.lastIndex;
|
lastMatchedIndex = re.lastIndex;
|
||||||
}
|
}
|
||||||
// Append trailing path part.
|
// Append trailing path part.
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,63 @@ describe('$route', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should route and fire change event when catch-all params are used', function() {
|
||||||
|
var log = '',
|
||||||
|
lastRoute,
|
||||||
|
nextRoute;
|
||||||
|
|
||||||
|
module(function($routeProvider) {
|
||||||
|
$routeProvider.when('/Book1/:book/Chapter/:chapter/*highlight/edit',
|
||||||
|
{controller: noop, templateUrl: 'Chapter.html'});
|
||||||
|
$routeProvider.when('/Book2/:book/*highlight/Chapter/:chapter',
|
||||||
|
{controller: noop, templateUrl: 'Chapter.html'});
|
||||||
|
$routeProvider.when('/Blank', {});
|
||||||
|
});
|
||||||
|
inject(function($route, $location, $rootScope) {
|
||||||
|
$rootScope.$on('$routeChangeStart', function(event, next, current) {
|
||||||
|
log += 'before();';
|
||||||
|
expect(current).toBe($route.current);
|
||||||
|
lastRoute = current;
|
||||||
|
nextRoute = next;
|
||||||
|
});
|
||||||
|
$rootScope.$on('$routeChangeSuccess', function(event, current, last) {
|
||||||
|
log += 'after();';
|
||||||
|
expect(current).toBe($route.current);
|
||||||
|
expect(lastRoute).toBe(last);
|
||||||
|
expect(nextRoute).toBe(current);
|
||||||
|
});
|
||||||
|
|
||||||
|
$location.path('/Book1/Moby/Chapter/Intro/one/edit').search('p=123');
|
||||||
|
$rootScope.$digest();
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(log).toEqual('before();after();');
|
||||||
|
expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', highlight:'one', p:'123'});
|
||||||
|
|
||||||
|
log = '';
|
||||||
|
$location.path('/Blank').search('ignore');
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(log).toEqual('before();after();');
|
||||||
|
expect($route.current.params).toEqual({ignore:true});
|
||||||
|
|
||||||
|
log = '';
|
||||||
|
$location.path('/Book1/Moby/Chapter/Intro/one/two/edit').search('p=123');
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(log).toEqual('before();after();');
|
||||||
|
expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', highlight:'one/two', p:'123'});
|
||||||
|
|
||||||
|
log = '';
|
||||||
|
$location.path('/Book2/Moby/one/two/Chapter/Intro').search('p=123');
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(log).toEqual('before();after();');
|
||||||
|
expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', highlight:'one/two', p:'123'});
|
||||||
|
|
||||||
|
log = '';
|
||||||
|
$location.path('/NONE');
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(log).toEqual('before();after();');
|
||||||
|
expect($route.current).toEqual(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should not change route when location is canceled', function() {
|
it('should not change route when location is canceled', function() {
|
||||||
module(function($routeProvider) {
|
module(function($routeProvider) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue