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;
|
||||
preserveQueryParams?: boolean;
|
||||
preserveFragment?: boolean;
|
||||
skipLocationChange?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,17 +262,21 @@ export class Router {
|
|||
*
|
||||
* ```
|
||||
* 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
|
||||
* 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) {
|
||||
return this.scheduleNavigation(url, false);
|
||||
return this.scheduleNavigation(url, extras);
|
||||
} else {
|
||||
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});
|
||||
*
|
||||
* // Navigate without updating the URL
|
||||
* router.navigate(['team', 33, 'team', '11], {relativeTo: route, skipLocationChange: true });
|
||||
* ```
|
||||
*
|
||||
* In opposite to `navigateByUrl`, `navigate` always takes a delta
|
||||
* that is applied to the current URL.
|
||||
*/
|
||||
navigate(commands: any[], extras: NavigationExtras = {}): Promise<boolean> {
|
||||
return this.scheduleNavigation(this.createUrlTree(commands, extras), false);
|
||||
navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: 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;
|
||||
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 {
|
||||
|
|
|
@ -113,6 +113,52 @@ describe('Integration', () => {
|
|||
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',
|
||||
fakeAsync(inject(
|
||||
[Router, TestComponentBuilder, Location],
|
||||
|
|
|
@ -106,6 +106,7 @@ export interface NavigationExtras {
|
|||
preserveQueryParams?: boolean;
|
||||
queryParams?: Params;
|
||||
relativeTo?: ActivatedRoute;
|
||||
skipLocationChange?: boolean;
|
||||
}
|
||||
|
||||
/** @stable */
|
||||
|
@ -173,7 +174,7 @@ export declare class Router {
|
|||
initialNavigation(): void;
|
||||
isActive(url: string | UrlTree, exact: boolean): boolean;
|
||||
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>;
|
||||
navigateByUrl(url: string | UrlTree): Promise<boolean>;
|
||||
navigateByUrl(url: string | UrlTree, extras?: NavigationExtras): Promise<boolean>;
|
||||
ngOnDestroy(): void;
|
||||
parseUrl(url: string): UrlTree;
|
||||
resetConfig(config: Routes): void;
|
||||
|
|
Loading…
Reference in New Issue