feat(router): Allow navigation without updating the URL (#9608)

This commit is contained in:
Brandon 2016-08-04 13:46:09 -05:00 committed by Alex Rickabaugh
parent 2b704f0586
commit 63b82cd730
3 changed files with 64 additions and 8 deletions

View File

@ -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 {

View File

@ -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],

View File

@ -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;