Skip to content

Commit

Permalink
fix(router): correctly handle string command in outlets (#39728)
Browse files Browse the repository at this point in the history
There are many places where examples use just a string for the command
in outlets. When using nested outlets, we do not correctly handle
this case, as the types and algorithm always expect an array.
This PR updates the `createUrlTree` algorithm to account for the
possibility of a string literal as the command for an outlet.

Fixes #18928

PR Close #39728
  • Loading branch information
atscott authored and AndrewKushnir committed Nov 20, 2020
1 parent 989d4d4 commit 50c19a2
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
17 changes: 12 additions & 5 deletions packages/router/src/create_url_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ function createPositionApplyingDoubleDots(
return new Position(g, false, ci - dd);
}

function getOutlets(commands: any[]): {[k: string]: any[]} {
function getOutlets(commands: unknown[]): {[k: string]: unknown[]|string} {
if (isCommandWithOutlets(commands[0])) {
return commands[0].outlets;
}
Expand Down Expand Up @@ -229,7 +229,10 @@ function updateSegmentGroupChildren(
const outlets = getOutlets(commands);
const children: {[key: string]: UrlSegmentGroup} = {};

forEach(outlets, (commands: any, outlet: string) => {
forEach(outlets, (commands, outlet) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
}
Expand Down Expand Up @@ -311,9 +314,13 @@ function createNewSegmentGroup(
return new UrlSegmentGroup(paths, {});
}

function createNewSegmentChildren(outlets: {[name: string]: any}): any {
const children: {[key: string]: UrlSegmentGroup} = {};
forEach(outlets, (commands: any, outlet: string) => {
function createNewSegmentChildren(outlets: {[name: string]: unknown[]|string}):
{[outlet: string]: UrlSegmentGroup} {
const children: {[outlet: string]: UrlSegmentGroup} = {};
forEach(outlets, (commands, outlet) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
}
Expand Down
7 changes: 7 additions & 0 deletions packages/router/test/create_url_tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ describe('createUrlTree', () => {
});
});

it('can navigate to nested route where commands is string', () => {
const p = serializer.parse('/');
const t = createRoot(
p, ['/', {outlets: {primary: ['child', {outlets: {primary: 'nested-primary'}}]}}]);
expect(serializer.serialize(t)).toEqual('/child/nested-primary');
});

it('should throw when outlets is not the last command', () => {
const p = serializer.parse('/a');
expect(() => createRoot(p, ['a', {outlets: {right: ['c']}}, 'c']))
Expand Down

0 comments on commit 50c19a2

Please sign in to comment.