feat(router): update routerLink DSL to handle aux routes

This commit is contained in:
vsavkin 2016-07-12 09:49:55 -07:00
parent 27436270fd
commit ded518d47f
3 changed files with 59 additions and 13 deletions

View File

@ -87,6 +87,20 @@ function normalizeCommands(commands: any[]): NormalizedNavigationCommands {
for (let i = 0; i < commands.length; ++i) { for (let i = 0; i < commands.length; ++i) {
const c = commands[i]; const c = commands[i];
if (typeof c === 'object' && c.outlets !== undefined) {
const r: {[k: string]: any} = {};
forEach(c.outlets, (commands: any, name: string) => {
const n = name === '' ? PRIMARY_OUTLET : name;
if (typeof commands === 'string') {
r[n] = commands.split('/');
} else {
r[n] = commands;
}
});
res.push({outlets: r});
continue;
}
if (!(typeof c === 'string')) { if (!(typeof c === 'string')) {
res.push(c); res.push(c);
continue; continue;
@ -140,15 +154,13 @@ function findStartingPosition(
} }
function getPath(command: any): any { function getPath(command: any): any {
if (!(typeof command === 'string')) return command.toString(); return `${command}`;
const parts = command.toString().split(':');
return parts.length > 1 ? parts[1] : command;
} }
function getOutlet(commands: any[]): string { function getOutlets(commands: any[]): {[k: string]: any[]} {
if (!(typeof commands[0] === 'string')) return PRIMARY_OUTLET; if (!(typeof commands[0] === 'object')) return {[PRIMARY_OUTLET]: commands};
const parts = commands[0].toString().split(':'); if (commands[0].outlets === undefined) return {[PRIMARY_OUTLET]: commands};
return parts.length > 1 ? parts[0] : PRIMARY_OUTLET; return commands[0].outlets;
} }
function updateSegment(segment: UrlSegment, startIndex: number, commands: any[]): UrlSegment { function updateSegment(segment: UrlSegment, startIndex: number, commands: any[]): UrlSegment {
@ -177,11 +189,17 @@ function updateSegmentChildren(
if (commands.length === 0) { if (commands.length === 0) {
return new UrlSegment(segment.pathsWithParams, {}); return new UrlSegment(segment.pathsWithParams, {});
} else { } else {
const outlet = getOutlet(commands); const outlets = getOutlets(commands);
const children: {[key: string]: UrlSegment} = {}; const children: {[key: string]: UrlSegment} = {};
children[outlet] = updateSegment(segment.children[outlet], startIndex, commands);
forEach(outlets, (commands: any, outlet: string) => {
if (commands !== null) {
children[outlet] = updateSegment(segment.children[outlet], startIndex, commands);
}
});
forEach(segment.children, (child: UrlSegment, childOutlet: string) => { forEach(segment.children, (child: UrlSegment, childOutlet: string) => {
if (childOutlet !== outlet) { if (outlets[childOutlet] === undefined) {
children[childOutlet] = child; children[childOutlet] = child;
} }
}); });
@ -201,7 +219,7 @@ function prefixedWith(segment: UrlSegment, startIndex: number, commands: any[])
const next = const next =
currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null; currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
if (curr && next && (typeof next === 'object')) { if (curr && next && (typeof next === 'object') && next.outlets === undefined) {
if (!compare(curr, next, path)) return noMatch; if (!compare(curr, next, path)) return noMatch;
currentCommandIndex += 2; currentCommandIndex += 2;
} else { } else {

View File

@ -209,6 +209,9 @@ export class Router {
* // you can collapse static fragments like this * // you can collapse static fragments like this
* router.createUrlTree(['/team/33/user', userId]); * router.createUrlTree(['/team/33/user', userId]);
* *
* // create /team/33/(user/11//aux:chat)
* router.createUrlTree(['/team', 33, {outlets: {"": 'user/11', right: 'chat'}}]);
*
* // assuming the current url is `/team/33/user/11` and the route points to `user/11` * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
* *
* // navigate to /team/33/user/11/details * // navigate to /team/33/user/11/details

View File

@ -8,6 +8,7 @@ import {DefaultUrlSerializer, UrlPathWithParams, UrlSegment, UrlTree} from '../s
describe('createUrlTree', () => { describe('createUrlTree', () => {
const serializer = new DefaultUrlSerializer(); const serializer = new DefaultUrlSerializer();
it('should navigate to the root', () => { it('should navigate to the root', () => {
const p = serializer.parse('/'); const p = serializer.parse('/');
const t = createRoot(p, ['/']); const t = createRoot(p, ['/']);
@ -42,16 +43,40 @@ describe('createUrlTree', () => {
it('should support updating secondary segments', () => { it('should support updating secondary segments', () => {
const p = serializer.parse('/a(right:b)'); const p = serializer.parse('/a(right:b)');
const t = createRoot(p, ['right:c', 11, 'd']); const t = createRoot(p, [{outlets: {right: ['c', 11, 'd']}}]);
expect(serializer.serialize(t)).toEqual('/a(right:c/11/d)'); expect(serializer.serialize(t)).toEqual('/a(right:c/11/d)');
}); });
it('should support updating secondary segments (nested case)', () => { it('should support updating secondary segments (nested case)', () => {
const p = serializer.parse('/a/(b//right:c)'); const p = serializer.parse('/a/(b//right:c)');
const t = createRoot(p, ['a', 'right:d', 11, 'e']); const t = createRoot(p, ['a', {outlets: {right: ['d', 11, 'e']}}]);
expect(serializer.serialize(t)).toEqual('/a/(b//right:d/11/e)'); expect(serializer.serialize(t)).toEqual('/a/(b//right:d/11/e)');
}); });
it('should support updating using a string', () => {
const p = serializer.parse('/a(right:b)');
const t = createRoot(p, [{outlets: {right: 'c/11/d'}}]);
expect(serializer.serialize(t)).toEqual('/a(right:c/11/d)');
});
it('should support updating primary and secondary segments at once', () => {
const p = serializer.parse('/a(right:b)');
const t = createRoot(p, [{outlets: {'': 'y/z', right: 'c/11/d'}}]);
expect(serializer.serialize(t)).toEqual('/y/z(right:c/11/d)');
});
it('should support removing primary segment', () => {
const p = serializer.parse('/a/(b//right:c)');
const t = createRoot(p, ['a', {outlets: {'': null, right: 'd'}}]);
expect(serializer.serialize(t)).toEqual('/a/(right:d)');
});
it('should support removing secondary segments', () => {
const p = serializer.parse('/a(right:b)');
const t = createRoot(p, [{outlets: {right: null}}]);
expect(serializer.serialize(t)).toEqual('/a');
});
it('should update matrix parameters', () => { it('should update matrix parameters', () => {
const p = serializer.parse('/a;pp=11'); const p = serializer.parse('/a;pp=11');
const t = createRoot(p, ['/a', {pp: 22, dd: 33}]); const t = createRoot(p, ['/a', {pp: 22, dd: 33}]);