fix(router): fix skipLocationChanges on RouterLink directives

fixes #13156
This commit is contained in:
Victor Berchet 2016-12-02 13:34:05 -08:00 committed by Alex Rickabaugh
parent 804943c9b1
commit f562cbf86c
2 changed files with 50 additions and 16 deletions

View File

@ -102,7 +102,8 @@ export class RouterLink {
@HostListener('click', []) @HostListener('click', [])
onClick(): boolean { onClick(): boolean {
this.router.navigateByUrl(this.urlTree); const extras = {skipLocationChange: attrBoolValue(this.skipLocationChange)};
this.router.navigateByUrl(this.urlTree, extras);
return true; return true;
} }
@ -111,10 +112,9 @@ export class RouterLink {
relativeTo: this.route, relativeTo: this.route,
queryParams: this.queryParams, queryParams: this.queryParams,
fragment: this.fragment, fragment: this.fragment,
preserveQueryParams: toBool(this.preserveQueryParams), preserveQueryParams: attrBoolValue(this.preserveQueryParams),
preserveFragment: toBool(this.preserveFragment), preserveFragment: attrBoolValue(this.preserveFragment),
skipLocationChange: toBool(this.skipLocationChange), replaceUrl: attrBoolValue(this.replaceUrl),
replaceUrl: toBool(this.replaceUrl),
}); });
} }
} }
@ -176,7 +176,8 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
return true; return true;
} }
this.router.navigateByUrl(this.urlTree); const extras = {skipLocationChange: attrBoolValue(this.skipLocationChange)};
this.router.navigateByUrl(this.urlTree, extras);
return false; return false;
} }
@ -189,14 +190,13 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
relativeTo: this.route, relativeTo: this.route,
queryParams: this.queryParams, queryParams: this.queryParams,
fragment: this.fragment, fragment: this.fragment,
preserveQueryParams: toBool(this.preserveQueryParams), preserveQueryParams: attrBoolValue(this.preserveQueryParams),
preserveFragment: toBool(this.preserveFragment), preserveFragment: attrBoolValue(this.preserveFragment),
skipLocationChange: toBool(this.skipLocationChange), replaceUrl: attrBoolValue(this.replaceUrl),
replaceUrl: toBool(this.replaceUrl),
}); });
} }
} }
function toBool(s: any): boolean { function attrBoolValue(s: any): boolean {
return s === '' || !!s; return s === '' || !!s;
} }

View File

@ -7,8 +7,9 @@
*/ */
import {CommonModule, Location} from '@angular/common'; import {CommonModule, Location} from '@angular/common';
import {Component, Injector, NgModule, NgModuleFactoryLoader} from '@angular/core'; import {Component, NgModule, NgModuleFactoryLoader} from '@angular/core';
import {ComponentFixture, TestBed, async, fakeAsync, inject, tick} from '@angular/core/testing'; import {ComponentFixture, TestBed, fakeAsync, inject, tick} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/matchers'; import {expect} from '@angular/platform-browser/testing/matchers';
import {Observable} from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
import {map} from 'rxjs/operator/map'; import {map} from 'rxjs/operator/map';
@ -18,7 +19,6 @@ import {RouterPreloader} from '../src/router_preloader';
import {forEach} from '../src/utils/collection'; import {forEach} from '../src/utils/collection';
import {RouterTestingModule, SpyNgModuleFactoryLoader} from '../testing'; import {RouterTestingModule, SpyNgModuleFactoryLoader} from '../testing';
describe('Integration', () => { describe('Integration', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -909,6 +909,37 @@ describe('Integration', () => {
}); });
describe('router links', () => { describe('router links', () => {
it('should support skipping location update for anchor router links',
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
const fixture = TestBed.createComponent(RootCmp);
advance(fixture);
router.resetConfig([{path: 'team/:id', component: TeamCmp}]);
router.navigateByUrl('/team/22');
advance(fixture);
expect(location.path()).toEqual('/team/22');
expect(fixture.nativeElement).toHaveText('team 22 [ , right: ]');
const teamCmp = fixture.debugElement.childNodes[1].componentInstance;
teamCmp.routerLink = ['/team/0'];
advance(fixture);
const anchor = fixture.debugElement.query(By.css('a')).nativeElement;
anchor.click();
advance(fixture);
expect(fixture.nativeElement).toHaveText('team 0 [ , right: ]');
expect(location.path()).toEqual('/team/22');
teamCmp.routerLink = ['/team/1'];
advance(fixture);
const button = fixture.debugElement.query(By.css('button')).nativeElement;
button.click();
advance(fixture);
expect(fixture.nativeElement).toHaveText('team 1 [ , right: ]');
expect(location.path()).toEqual('/team/22');
})));
it('should support string router links', fakeAsync(inject([Router], (router: Router) => { it('should support string router links', fakeAsync(inject([Router], (router: Router) => {
const fixture = createRoot(router, RootCmp); const fixture = createRoot(router, RootCmp);
@ -2591,12 +2622,15 @@ class BlankCmp {
@Component({ @Component({
selector: 'team-cmp', selector: 'team-cmp',
template: template: `team {{id | async}} ` +
`team {{id | async}} [ <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> ]` `[ <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> ]` +
`<a [routerLink]="routerLink" skipLocationChange></a>` +
`<button [routerLink]="routerLink" skipLocationChange></button>`
}) })
class TeamCmp { class TeamCmp {
id: Observable<string>; id: Observable<string>;
recordedParams: Params[] = []; recordedParams: Params[] = [];
routerLink = ['.'];
constructor(public route: ActivatedRoute) { constructor(public route: ActivatedRoute) {
this.id = map.call(route.params, (p: any) => p['id']); this.id = map.call(route.params, (p: any) => p['id']);