fix(router): Fix relative link generation from empty path components (#37446)
Partial resubmit of #26243 Fixes incorrect url tree generation for empty path components with children. Adds a test to demonstrate the failure of createUrlTree for those routes. Fixes #13011 Fixes #35687 PR Close #37446
This commit is contained in:
parent
946f1179e9
commit
8d817daf78
|
@ -148,7 +148,12 @@ function findStartingPosition(nav: Navigation, tree: UrlTree, route: ActivatedRo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route.snapshot._lastPathIndex === -1) {
|
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;
|
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {BehaviorSubject} from 'rxjs';
|
||||||
import {createUrlTree} from '../src/create_url_tree';
|
import {createUrlTree} from '../src/create_url_tree';
|
||||||
import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute} from '../src/router_state';
|
import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute} from '../src/router_state';
|
||||||
import {Params, PRIMARY_OUTLET} from '../src/shared';
|
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', () => {
|
describe('createUrlTree', () => {
|
||||||
const serializer = new DefaultUrlSerializer();
|
const serializer = new DefaultUrlSerializer();
|
||||||
|
@ -240,6 +240,29 @@ describe('createUrlTree', () => {
|
||||||
const t = createRoot(p, [], {}, 'fragment');
|
const t = createRoot(p, [], {}, 'fragment');
|
||||||
expect(t.fragment).toEqual('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) {
|
function createRoot(tree: UrlTree, commands: any[], queryParams?: Params, fragment?: string) {
|
||||||
|
@ -260,8 +283,8 @@ function create(
|
||||||
expect(segment).toBeDefined();
|
expect(segment).toBeDefined();
|
||||||
}
|
}
|
||||||
const s = new (ActivatedRouteSnapshot as any)(
|
const s = new (ActivatedRouteSnapshot as any)(
|
||||||
[], <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null, <any>segment,
|
segment.segments, <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null,
|
||||||
startIndex, <any>null);
|
<any>segment, startIndex, <any>null);
|
||||||
const a = new (ActivatedRoute as any)(
|
const a = new (ActivatedRoute as any)(
|
||||||
new BehaviorSubject(null!), new BehaviorSubject(null!), new BehaviorSubject(null!),
|
new BehaviorSubject(null!), new BehaviorSubject(null!), new BehaviorSubject(null!),
|
||||||
new BehaviorSubject(null!), new BehaviorSubject(null!), PRIMARY_OUTLET, 'someComponent', s);
|
new BehaviorSubject(null!), new BehaviorSubject(null!), PRIMARY_OUTLET, 'someComponent', s);
|
||||||
|
|
Loading…
Reference in New Issue