feat(router): Allow navigation without updating the URL (#9608)
This commit is contained in:
parent
2b704f0586
commit
63b82cd730
|
@ -46,6 +46,7 @@ export interface NavigationExtras {
|
||||||
fragment?: string;
|
fragment?: string;
|
||||||
preserveQueryParams?: boolean;
|
preserveQueryParams?: boolean;
|
||||||
preserveFragment?: boolean;
|
preserveFragment?: boolean;
|
||||||
|
skipLocationChange?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,17 +262,21 @@ export class Router {
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* router.navigateByUrl("/team/33/user/11");
|
* router.navigateByUrl("/team/33/user/11");
|
||||||
|
*
|
||||||
|
* // Navigate without updating the URL
|
||||||
|
* router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* In opposite to `navigate`, `navigateByUrl` takes a whole URL
|
* In opposite to `navigate`, `navigateByUrl` takes a whole URL
|
||||||
* and does not apply any delta to the current one.
|
* and does not apply any delta to the current one.
|
||||||
*/
|
*/
|
||||||
navigateByUrl(url: string|UrlTree): Promise<boolean> {
|
navigateByUrl(url: string|UrlTree, extras: NavigationExtras = {skipLocationChange: false}):
|
||||||
|
Promise<boolean> {
|
||||||
if (url instanceof UrlTree) {
|
if (url instanceof UrlTree) {
|
||||||
return this.scheduleNavigation(url, false);
|
return this.scheduleNavigation(url, extras);
|
||||||
} else {
|
} else {
|
||||||
const urlTree = this.urlSerializer.parse(url);
|
const urlTree = this.urlSerializer.parse(url);
|
||||||
return this.scheduleNavigation(urlTree, false);
|
return this.scheduleNavigation(urlTree, extras);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,13 +293,17 @@ export class Router {
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* router.navigate(['team', 33, 'team', '11], {relativeTo: route});
|
* router.navigate(['team', 33, 'team', '11], {relativeTo: route});
|
||||||
|
*
|
||||||
|
* // Navigate without updating the URL
|
||||||
|
* router.navigate(['team', 33, 'team', '11], {relativeTo: route, skipLocationChange: true });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* In opposite to `navigateByUrl`, `navigate` always takes a delta
|
* In opposite to `navigateByUrl`, `navigate` always takes a delta
|
||||||
* that is applied to the current URL.
|
* that is applied to the current URL.
|
||||||
*/
|
*/
|
||||||
navigate(commands: any[], extras: NavigationExtras = {}): Promise<boolean> {
|
navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}):
|
||||||
return this.scheduleNavigation(this.createUrlTree(commands, extras), false);
|
Promise<boolean> {
|
||||||
|
return this.scheduleNavigation(this.createUrlTree(commands, extras), extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,10 +328,10 @@ export class Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private scheduleNavigation(url: UrlTree, preventPushState: boolean): Promise<boolean> {
|
private scheduleNavigation(url: UrlTree, extras: NavigationExtras): Promise<boolean> {
|
||||||
const id = ++this.navigationId;
|
const id = ++this.navigationId;
|
||||||
this.routerEvents.next(new NavigationStart(id, this.serializeUrl(url)));
|
this.routerEvents.next(new NavigationStart(id, this.serializeUrl(url)));
|
||||||
return Promise.resolve().then((_) => this.runNavigate(url, preventPushState, id));
|
return Promise.resolve().then((_) => this.runNavigate(url, extras.skipLocationChange, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private setUpLocationChangeListener(): void {
|
private setUpLocationChangeListener(): void {
|
||||||
|
|
|
@ -113,6 +113,52 @@ describe('Integration', () => {
|
||||||
expect(location.path()).toEqual('/team/33');
|
expect(location.path()).toEqual('/team/33');
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
it('should skip location update when using NavigationExtras.skipLocationChange with navigateByUrl',
|
||||||
|
fakeAsync(inject(
|
||||||
|
[Router, TestComponentBuilder, Location],
|
||||||
|
(router: Router, tcb: TestComponentBuilder, location: Location) => {
|
||||||
|
const fixture = tcb.createFakeAsync(RootCmp);
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
router.resetConfig([{path: 'team/:id', component: TeamCmp}]);
|
||||||
|
|
||||||
|
router.navigateByUrl('/team/22');
|
||||||
|
advance(fixture);
|
||||||
|
expect(location.path()).toEqual('/team/22');
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 22 [ , right: ]');
|
||||||
|
|
||||||
|
router.navigateByUrl('/team/33', {skipLocationChange: true});
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
expect(location.path()).toEqual('/team/22');
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 33 [ , right: ]');
|
||||||
|
})));
|
||||||
|
|
||||||
|
it('should skip location update when using NavigationExtras.skipLocationChange with navigate',
|
||||||
|
fakeAsync(inject(
|
||||||
|
[Router, TestComponentBuilder, Location],
|
||||||
|
(router: Router, tcb: TestComponentBuilder, location: Location) => {
|
||||||
|
const fixture = tcb.createFakeAsync(RootCmp);
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
router.resetConfig([{path: 'team/:id', component: TeamCmp}]);
|
||||||
|
|
||||||
|
router.navigate(['/team/22']);
|
||||||
|
advance(fixture);
|
||||||
|
expect(location.path()).toEqual('/team/22');
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 22 [ , right: ]');
|
||||||
|
|
||||||
|
router.navigate(['/team/33'], {skipLocationChange: true});
|
||||||
|
advance(fixture);
|
||||||
|
|
||||||
|
expect(location.path()).toEqual('/team/22');
|
||||||
|
|
||||||
|
expect(fixture.debugElement.nativeElement).toHaveText('team 33 [ , right: ]');
|
||||||
|
})));
|
||||||
|
|
||||||
it('should navigate back and forward',
|
it('should navigate back and forward',
|
||||||
fakeAsync(inject(
|
fakeAsync(inject(
|
||||||
[Router, TestComponentBuilder, Location],
|
[Router, TestComponentBuilder, Location],
|
||||||
|
|
|
@ -106,6 +106,7 @@ export interface NavigationExtras {
|
||||||
preserveQueryParams?: boolean;
|
preserveQueryParams?: boolean;
|
||||||
queryParams?: Params;
|
queryParams?: Params;
|
||||||
relativeTo?: ActivatedRoute;
|
relativeTo?: ActivatedRoute;
|
||||||
|
skipLocationChange?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
|
@ -173,7 +174,7 @@ export declare class Router {
|
||||||
initialNavigation(): void;
|
initialNavigation(): void;
|
||||||
isActive(url: string | UrlTree, exact: boolean): boolean;
|
isActive(url: string | UrlTree, exact: boolean): boolean;
|
||||||
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>;
|
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>;
|
||||||
navigateByUrl(url: string | UrlTree): Promise<boolean>;
|
navigateByUrl(url: string | UrlTree, extras?: NavigationExtras): Promise<boolean>;
|
||||||
ngOnDestroy(): void;
|
ngOnDestroy(): void;
|
||||||
parseUrl(url: string): UrlTree;
|
parseUrl(url: string): UrlTree;
|
||||||
resetConfig(config: Routes): void;
|
resetConfig(config: Routes): void;
|
||||||
|
|
Loading…
Reference in New Issue