diff --git a/packages/router/src/create_url_tree.ts b/packages/router/src/create_url_tree.ts index ae185e34e2..bc560f8524 100644 --- a/packages/router/src/create_url_tree.ts +++ b/packages/router/src/create_url_tree.ts @@ -148,7 +148,12 @@ function findStartingPosition(nav: Navigation, tree: UrlTree, route: ActivatedRo } if (route.snapshot._lastPathIndex === -1) { - return new Position(route.snapshot._urlSegment, true, 0); + const segmentGroup = route.snapshot._urlSegment; + // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children + // see issue #26224, #13011, #35687 + // However, if the ActivatedRoute is the root we should process children like above. + const processChildren = segmentGroup === tree.root; + return new Position(segmentGroup, processChildren, 0); } const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1; diff --git a/packages/router/test/create_url_tree.spec.ts b/packages/router/test/create_url_tree.spec.ts index f83157abe5..36cd73c789 100644 --- a/packages/router/test/create_url_tree.spec.ts +++ b/packages/router/test/create_url_tree.spec.ts @@ -11,7 +11,7 @@ import {BehaviorSubject} from 'rxjs'; import {createUrlTree} from '../src/create_url_tree'; import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute} from '../src/router_state'; import {Params, PRIMARY_OUTLET} from '../src/shared'; -import {DefaultUrlSerializer, UrlSegmentGroup, UrlTree} from '../src/url_tree'; +import {DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlTree} from '../src/url_tree'; describe('createUrlTree', () => { const serializer = new DefaultUrlSerializer(); @@ -240,6 +240,29 @@ describe('createUrlTree', () => { const t = createRoot(p, [], {}, 'fragment'); expect(t.fragment).toEqual('fragment'); }); + + it('should support pathless route', () => { + const p = serializer.parse('/a'); + const t = create(p.root.children[PRIMARY_OUTLET], -1, p, ['b']); + expect(serializer.serialize(t)).toEqual('/b'); + }); + + it('should support pathless route with ../ at root', () => { + const p = serializer.parse('/a'); + const t = create(p.root.children[PRIMARY_OUTLET], -1, p, ['../b']); + expect(serializer.serialize(t)).toEqual('/b'); + }); + + it('should support pathless child of pathless root', () => { + // i.e. routes = {path: '', loadChildren: () => import('child')...} + // forChild: {path: '', component: Comp} + const p = serializer.parse(''); + const empty = new UrlSegmentGroup([], {}); + p.root.children[PRIMARY_OUTLET] = empty; + empty.parent = p.root; + const t = create(empty, -1, p, ['lazy']); + expect(serializer.serialize(t)).toEqual('/lazy'); + }); }); function createRoot(tree: UrlTree, commands: any[], queryParams?: Params, fragment?: string) { @@ -260,8 +283,8 @@ function create( expect(segment).toBeDefined(); } const s = new (ActivatedRouteSnapshot as any)( - [], {}, {}, '', {}, PRIMARY_OUTLET, 'someComponent', null, segment, - startIndex, null); + segment.segments, {}, {}, '', {}, PRIMARY_OUTLET, 'someComponent', null, + segment, startIndex, null); const a = new (ActivatedRoute as any)( new BehaviorSubject(null!), new BehaviorSubject(null!), new BehaviorSubject(null!), new BehaviorSubject(null!), new BehaviorSubject(null!), PRIMARY_OUTLET, 'someComponent', s);