fix(router): state data missing in routerLink (#36462)
fixes #33173 - router state data is missing on routerLink when used with non-anchor elements. PR Close #36462
This commit is contained in:
parent
95fc3d4c5c
commit
e0415dbf16
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {LocationStrategy} from '@angular/common';
|
||||
import {Attribute, Directive, ElementRef, HostBinding, HostListener, Input, OnChanges, OnDestroy, Renderer2, isDevMode} from '@angular/core';
|
||||
import {Attribute, Directive, ElementRef, HostBinding, HostListener, Input, isDevMode, OnChanges, OnDestroy, Renderer2} from '@angular/core';
|
||||
import {Subscription} from 'rxjs';
|
||||
|
||||
import {QueryParamsHandling} from '../config';
|
||||
|
@ -114,21 +114,21 @@ import {UrlTree} from '../url_tree';
|
|||
@Directive({selector: ':not(a):not(area)[routerLink]'})
|
||||
export class RouterLink {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() queryParams !: {[k: string]: any};
|
||||
@Input() queryParams!: {[k: string]: any};
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() fragment !: string;
|
||||
@Input() fragment!: string;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() queryParamsHandling !: QueryParamsHandling;
|
||||
@Input() queryParamsHandling!: QueryParamsHandling;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() preserveFragment !: boolean;
|
||||
@Input() preserveFragment!: boolean;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() skipLocationChange !: boolean;
|
||||
@Input() skipLocationChange!: boolean;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() replaceUrl !: boolean;
|
||||
@Input() replaceUrl!: boolean;
|
||||
@Input() state?: {[k: string]: any};
|
||||
private commands: any[] = [];
|
||||
// TODO(issue/24571): remove '!'.
|
||||
private preserve !: boolean;
|
||||
private preserve!: boolean;
|
||||
|
||||
constructor(
|
||||
private router: Router, private route: ActivatedRoute,
|
||||
|
@ -163,6 +163,7 @@ export class RouterLink {
|
|||
const extras = {
|
||||
skipLocationChange: attrBoolValue(this.skipLocationChange),
|
||||
replaceUrl: attrBoolValue(this.replaceUrl),
|
||||
state: this.state,
|
||||
};
|
||||
this.router.navigateByUrl(this.urlTree, extras);
|
||||
return true;
|
||||
|
@ -194,28 +195,28 @@ export class RouterLink {
|
|||
@Directive({selector: 'a[routerLink],area[routerLink]'})
|
||||
export class RouterLinkWithHref implements OnChanges, OnDestroy {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@HostBinding('attr.target') @Input() target !: string;
|
||||
@HostBinding('attr.target') @Input() target!: string;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() queryParams !: {[k: string]: any};
|
||||
@Input() queryParams!: {[k: string]: any};
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() fragment !: string;
|
||||
@Input() fragment!: string;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() queryParamsHandling !: QueryParamsHandling;
|
||||
@Input() queryParamsHandling!: QueryParamsHandling;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() preserveFragment !: boolean;
|
||||
@Input() preserveFragment!: boolean;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() skipLocationChange !: boolean;
|
||||
@Input() skipLocationChange!: boolean;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@Input() replaceUrl !: boolean;
|
||||
@Input() replaceUrl!: boolean;
|
||||
@Input() state?: {[k: string]: any};
|
||||
private commands: any[] = [];
|
||||
private subscription: Subscription;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
private preserve !: boolean;
|
||||
private preserve!: boolean;
|
||||
|
||||
// the url displayed on the anchor element.
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@HostBinding() href !: string;
|
||||
@HostBinding() href!: string;
|
||||
|
||||
constructor(
|
||||
private router: Router, private route: ActivatedRoute,
|
||||
|
@ -244,8 +245,12 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
|
|||
this.preserve = value;
|
||||
}
|
||||
|
||||
ngOnChanges(changes: {}): any { this.updateTargetUrlAndHref(); }
|
||||
ngOnDestroy(): any { this.subscription.unsubscribe(); }
|
||||
ngOnChanges(changes: {}): any {
|
||||
this.updateTargetUrlAndHref();
|
||||
}
|
||||
ngOnDestroy(): any {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event.button', '$event.ctrlKey', '$event.metaKey', '$event.shiftKey'])
|
||||
onClick(button: number, ctrlKey: boolean, metaKey: boolean, shiftKey: boolean): boolean {
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
import {CommonModule, Location} from '@angular/common';
|
||||
import {SpyLocation} from '@angular/common/testing';
|
||||
import {ChangeDetectionStrategy, Component, Injectable, NgModule, NgModuleFactoryLoader, NgModuleRef, NgZone, OnDestroy, ɵConsole as Console, ɵNoopNgZone as NoopNgZone} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, fakeAsync, inject, tick} from '@angular/core/testing';
|
||||
import {ComponentFixture, fakeAsync, inject, TestBed, tick} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, CanActivate, CanDeactivate, ChildActivationEnd, ChildActivationStart, DefaultUrlSerializer, DetachedRouteHandle, Event, GuardsCheckEnd, GuardsCheckStart, Navigation, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, PRIMARY_OUTLET, ParamMap, Params, PreloadAllModules, PreloadingStrategy, Resolve, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterModule, RouterPreloader, RouterStateSnapshot, RoutesRecognized, RunGuardsAndResolvers, UrlHandlingStrategy, UrlSegmentGroup, UrlSerializer, UrlTree} from '@angular/router';
|
||||
import {Observable, Observer, Subscription, of } from 'rxjs';
|
||||
import {ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, CanActivate, CanDeactivate, ChildActivationEnd, ChildActivationStart, DefaultUrlSerializer, DetachedRouteHandle, Event, GuardsCheckEnd, GuardsCheckStart, Navigation, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ParamMap, Params, PreloadAllModules, PreloadingStrategy, PRIMARY_OUTLET, Resolve, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouteReuseStrategy, RouterEvent, RouterModule, RouterPreloader, RouterStateSnapshot, RoutesRecognized, RunGuardsAndResolvers, UrlHandlingStrategy, UrlSegmentGroup, UrlSerializer, UrlTree} from '@angular/router';
|
||||
import {Observable, Observer, of, Subscription} from 'rxjs';
|
||||
import {filter, first, map, tap} from 'rxjs/operators';
|
||||
|
||||
import {forEach} from '../src/utils/collection';
|
||||
|
@ -129,8 +129,8 @@ describe('Integration', () => {
|
|||
router.navigateByUrl('/simple');
|
||||
tick();
|
||||
|
||||
expect(event !.navigationTrigger).toEqual('imperative');
|
||||
expect(event !.restoredState).toEqual(null);
|
||||
expect(event!.navigationTrigger).toEqual('imperative');
|
||||
expect(event!.restoredState).toEqual(null);
|
||||
})));
|
||||
|
||||
it('should set history.state if passed using imperative navigation',
|
||||
|
@ -141,10 +141,10 @@ describe('Integration', () => {
|
|||
]);
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
let navigation: Navigation = null !;
|
||||
let navigation: Navigation = null!;
|
||||
router.events.subscribe(e => {
|
||||
if (e instanceof NavigationStart) {
|
||||
navigation = router.getCurrentNavigation() !;
|
||||
navigation = router.getCurrentNavigation()!;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -255,7 +255,9 @@ describe('Integration', () => {
|
|||
let warnings: string[] = [];
|
||||
|
||||
class MockConsole {
|
||||
warn(message: string) { warnings.push(message); }
|
||||
warn(message: string) {
|
||||
warnings.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -266,7 +268,9 @@ describe('Integration', () => {
|
|||
describe('with NgZone enabled', () => {
|
||||
it('should warn when triggered outside Angular zone',
|
||||
fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => {
|
||||
ngZone.runOutsideAngular(() => { router.navigateByUrl('/simple'); });
|
||||
ngZone.runOutsideAngular(() => {
|
||||
router.navigateByUrl('/simple');
|
||||
});
|
||||
|
||||
expect(warnings.length).toBe(1);
|
||||
expect(warnings[0])
|
||||
|
@ -276,19 +280,24 @@ describe('Integration', () => {
|
|||
|
||||
it('should not warn when triggered inside Angular zone',
|
||||
fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => {
|
||||
ngZone.run(() => { router.navigateByUrl('/simple'); });
|
||||
ngZone.run(() => {
|
||||
router.navigateByUrl('/simple');
|
||||
});
|
||||
|
||||
expect(warnings.length).toBe(0);
|
||||
})));
|
||||
});
|
||||
|
||||
describe('with NgZone disabled', () => {
|
||||
beforeEach(() => { TestBed.overrideProvider(NgZone, {useValue: new NoopNgZone()}); });
|
||||
beforeEach(() => {
|
||||
TestBed.overrideProvider(NgZone, {useValue: new NoopNgZone()});
|
||||
});
|
||||
|
||||
it('should not warn when triggered outside Angular zone',
|
||||
fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => {
|
||||
|
||||
ngZone.runOutsideAngular(() => { router.navigateByUrl('/simple'); });
|
||||
ngZone.runOutsideAngular(() => {
|
||||
router.navigateByUrl('/simple');
|
||||
});
|
||||
|
||||
expect(warnings.length).toBe(0);
|
||||
})));
|
||||
|
@ -331,18 +340,24 @@ describe('Integration', () => {
|
|||
@Component({template: '<router-outlet></router-outlet>'})
|
||||
class Parent {
|
||||
constructor(route: ActivatedRoute) {
|
||||
route.params.subscribe((s: any) => { log.push(s); });
|
||||
route.params.subscribe((s: any) => {
|
||||
log.push(s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Component({template: 'child1'})
|
||||
class Child1 {
|
||||
ngOnDestroy() { log.push('child1 destroy'); }
|
||||
ngOnDestroy() {
|
||||
log.push('child1 destroy');
|
||||
}
|
||||
}
|
||||
|
||||
@Component({template: 'child2'})
|
||||
class Child2 {
|
||||
constructor() { log.push('child2 constructor'); }
|
||||
constructor() {
|
||||
log.push('child2 constructor');
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
@ -382,7 +397,6 @@ describe('Integration', () => {
|
|||
'child2 constructor',
|
||||
]);
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
it('should not wait for prior navigations to start a new navigation',
|
||||
|
@ -412,7 +426,6 @@ describe('Integration', () => {
|
|||
'trueRightAway', 'trueIn2Seconds-start', 'trueRightAway', 'trueIn2Seconds-start',
|
||||
'trueIn2Seconds-end', 'trueIn2Seconds-end'
|
||||
]);
|
||||
|
||||
})));
|
||||
});
|
||||
|
||||
|
@ -464,11 +477,9 @@ describe('Integration', () => {
|
|||
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [{path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
router.resetConfig([
|
||||
{path: 'team/:id', component: TeamCmp, children: [{path: 'simple', component: SimpleCmp}]}
|
||||
]);
|
||||
|
||||
router.navigateByUrl('/team/33/simple');
|
||||
advance(fixture);
|
||||
|
@ -535,7 +546,9 @@ describe('Integration', () => {
|
|||
@Component({template: `record`})
|
||||
class RecordLocationCmp {
|
||||
private storedPath: string;
|
||||
constructor(loc: Location) { this.storedPath = loc.path(); }
|
||||
constructor(loc: Location) {
|
||||
this.storedPath = loc.path();
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [RecordLocationCmp], entryComponents: [RecordLocationCmp]})
|
||||
|
@ -632,11 +645,12 @@ describe('Integration', () => {
|
|||
providers: [{
|
||||
provide: 'authGuardFail',
|
||||
useValue: (a: any, b: any) => {
|
||||
return new Promise(res => { setTimeout(() => res(serializer.parse('/login')), 1); });
|
||||
return new Promise(res => {
|
||||
setTimeout(() => res(serializer.parse('/login')), 1);
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
@ -657,7 +671,7 @@ describe('Integration', () => {
|
|||
(router as any).hooks.beforePreactivation = () => {
|
||||
expect(location.path()).toEqual('/team/33');
|
||||
expect(fixture.nativeElement).toHaveText('team 22 [ , right: ]');
|
||||
return of (null);
|
||||
return of(null);
|
||||
};
|
||||
router.navigateByUrl('/team/33');
|
||||
|
||||
|
@ -758,7 +772,6 @@ describe('Integration', () => {
|
|||
|
||||
it('should should set `state` with urlUpdateStrategy="eagar"',
|
||||
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||
|
||||
router.urlUpdateStrategy = 'eager';
|
||||
router.resetConfig([
|
||||
{path: '', component: SimpleCmp},
|
||||
|
@ -766,10 +779,10 @@ describe('Integration', () => {
|
|||
]);
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
let navigation: Navigation = null !;
|
||||
let navigation: Navigation = null!;
|
||||
router.events.subscribe(e => {
|
||||
if (e instanceof NavigationStart) {
|
||||
navigation = router.getCurrentNavigation() !;
|
||||
navigation = router.getCurrentNavigation()!;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -806,24 +819,24 @@ describe('Integration', () => {
|
|||
router.navigateByUrl('/team/33/simple');
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/team/33/simple');
|
||||
const simpleNavStart = event !;
|
||||
const simpleNavStart = event!;
|
||||
|
||||
router.navigateByUrl('/team/22/user/victor');
|
||||
advance(fixture);
|
||||
const userVictorNavStart = event !;
|
||||
const userVictorNavStart = event!;
|
||||
|
||||
|
||||
location.back();
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/team/33/simple');
|
||||
expect(event !.navigationTrigger).toEqual('hashchange');
|
||||
expect(event !.restoredState !.navigationId).toEqual(simpleNavStart.id);
|
||||
expect(event!.navigationTrigger).toEqual('hashchange');
|
||||
expect(event!.restoredState!.navigationId).toEqual(simpleNavStart.id);
|
||||
|
||||
location.forward();
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/team/22/user/victor');
|
||||
expect(event !.navigationTrigger).toEqual('hashchange');
|
||||
expect(event !.restoredState !.navigationId).toEqual(userVictorNavStart.id);
|
||||
expect(event!.navigationTrigger).toEqual('hashchange');
|
||||
expect(event!.restoredState!.navigationId).toEqual(userVictorNavStart.id);
|
||||
})));
|
||||
|
||||
it('should navigate to the same url when config changes',
|
||||
|
@ -1115,8 +1128,8 @@ describe('Integration', () => {
|
|||
const user = fixture.debugElement.children[1].componentInstance;
|
||||
|
||||
let r1: any, r2: any;
|
||||
router.navigateByUrl('/user/victor') !.then(_ => r1 = _);
|
||||
router.navigateByUrl('/user/fedor') !.then(_ => r2 = _);
|
||||
router.navigateByUrl('/user/victor')!.then(_ => r1 = _);
|
||||
router.navigateByUrl('/user/fedor')!.then(_ => r2 = _);
|
||||
advance(fixture);
|
||||
|
||||
expect(r1).toEqual(false); // returns false because it was canceled
|
||||
|
@ -1185,7 +1198,7 @@ describe('Integration', () => {
|
|||
router.events.forEach(e => recordedEvents.push(e));
|
||||
|
||||
let e: any;
|
||||
router.navigateByUrl('/invalid') !.catch(_ => e = _);
|
||||
router.navigateByUrl('/invalid')!.catch(_ => e = _);
|
||||
advance(fixture);
|
||||
expect(e.message).toContain('Cannot match any routes');
|
||||
|
||||
|
@ -1254,7 +1267,7 @@ describe('Integration', () => {
|
|||
|
||||
router.navigateByUrl('/simple1');
|
||||
advance(fixture);
|
||||
const simple1NavStart = event !;
|
||||
const simple1NavStart = event!;
|
||||
|
||||
router.navigateByUrl('/throwing').catch(() => null);
|
||||
advance(fixture);
|
||||
|
@ -1265,7 +1278,7 @@ describe('Integration', () => {
|
|||
location.back();
|
||||
tick();
|
||||
|
||||
expect(event !.restoredState !.navigationId).toEqual(simple1NavStart.id);
|
||||
expect(event!.restoredState!.navigationId).toEqual(simple1NavStart.id);
|
||||
}));
|
||||
|
||||
it('should not trigger another navigation when resetting the url back due to a NavigationError',
|
||||
|
@ -1295,7 +1308,6 @@ describe('Integration', () => {
|
|||
// we do not trigger another navigation to /simple
|
||||
expect(events).toEqual(['/simple', '/throwing']);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
it('should dispatch NavigationCancel after the url has been reset back', fakeAsync(() => {
|
||||
|
@ -1341,7 +1353,7 @@ describe('Integration', () => {
|
|||
router.events.forEach(e => recordedEvents.push(e));
|
||||
|
||||
let e: any;
|
||||
router.navigateByUrl('/invalid') !.then(_ => e = _);
|
||||
router.navigateByUrl('/invalid')!.then(_ => e = _);
|
||||
advance(fixture);
|
||||
expect(e).toEqual('resolvedValue');
|
||||
|
||||
|
@ -1360,8 +1372,9 @@ describe('Integration', () => {
|
|||
it('should support custom malformed uri error handler',
|
||||
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const customMalformedUriErrorHandler =
|
||||
(e: URIError, urlSerializer: UrlSerializer, url: string):
|
||||
UrlTree => { return urlSerializer.parse('/?error=The-URL-you-went-to-is-invalid'); };
|
||||
(e: URIError, urlSerializer: UrlSerializer, url: string): UrlTree => {
|
||||
return urlSerializer.parse('/?error=The-URL-you-went-to-is-invalid');
|
||||
};
|
||||
router.malformedUriErrorHandler = customMalformedUriErrorHandler;
|
||||
|
||||
router.resetConfig([{path: 'simple', component: SimpleCmp}]);
|
||||
|
@ -1482,9 +1495,13 @@ describe('Integration', () => {
|
|||
activations: any[] = [];
|
||||
deactivations: any[] = [];
|
||||
|
||||
recordActivate(component: any): void { this.activations.push(component); }
|
||||
recordActivate(component: any): void {
|
||||
this.activations.push(component);
|
||||
}
|
||||
|
||||
recordDeactivate(component: any): void { this.deactivations.push(component); }
|
||||
recordDeactivate(component: any): void {
|
||||
this.deactivations.push(component);
|
||||
}
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Container]});
|
||||
|
@ -1517,7 +1534,6 @@ describe('Integration', () => {
|
|||
|
||||
it('should update url and router state before activating components',
|
||||
fakeAsync(inject([Router], (router: Router) => {
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([{path: 'cmp', component: ComponentRecordingRoutePathAndUrl}]);
|
||||
|
@ -1535,7 +1551,9 @@ describe('Integration', () => {
|
|||
|
||||
describe('data', () => {
|
||||
class ResolveSix implements Resolve<number> {
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): number { return 6; }
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): number {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -1601,7 +1619,7 @@ describe('Integration', () => {
|
|||
router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e));
|
||||
|
||||
let e: any = null;
|
||||
router.navigateByUrl('/simple') !.catch(error => e = error);
|
||||
router.navigateByUrl('/simple')!.catch(error => e = error);
|
||||
advance(fixture);
|
||||
|
||||
expectEvents(recordedEvents, [
|
||||
|
@ -1695,7 +1713,7 @@ describe('Integration', () => {
|
|||
{
|
||||
provide: 'resolver2',
|
||||
useValue: () => {
|
||||
return of (null).pipe(map(() => {
|
||||
return of(null).pipe(map(() => {
|
||||
log.push('resolver2');
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
|
@ -1764,9 +1782,8 @@ describe('Integration', () => {
|
|||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'link', component: StringLinkCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
children:
|
||||
[{path: 'link', component: StringLinkCmp}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
router.navigateByUrl('/team/22/link');
|
||||
|
@ -1825,7 +1842,6 @@ describe('Integration', () => {
|
|||
}));
|
||||
|
||||
it('should update hrefs when query params or fragment change', fakeAsync(() => {
|
||||
|
||||
@Component({
|
||||
selector: 'someRoot',
|
||||
template:
|
||||
|
@ -1855,7 +1871,6 @@ describe('Integration', () => {
|
|||
}));
|
||||
|
||||
it('should correctly use the preserve strategy', fakeAsync(() => {
|
||||
|
||||
@Component({
|
||||
selector: 'someRoot',
|
||||
template:
|
||||
|
@ -1877,7 +1892,6 @@ describe('Integration', () => {
|
|||
}));
|
||||
|
||||
it('should correctly use the merge strategy', fakeAsync(() => {
|
||||
|
||||
@Component({
|
||||
selector: 'someRoot',
|
||||
template:
|
||||
|
@ -1905,8 +1919,7 @@ describe('Integration', () => {
|
|||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'link', component: StringLinkButtonCmp},
|
||||
{path: 'simple', component: SimpleCmp}
|
||||
{path: 'link', component: StringLinkButtonCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
}]);
|
||||
|
||||
|
@ -1928,9 +1941,8 @@ describe('Integration', () => {
|
|||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'link', component: AbsoluteLinkCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
children:
|
||||
[{path: 'link', component: AbsoluteLinkCmp}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
router.navigateByUrl('/team/22/link');
|
||||
|
@ -1951,9 +1963,8 @@ describe('Integration', () => {
|
|||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'link', component: RelativeLinkCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
children:
|
||||
[{path: 'link', component: RelativeLinkCmp}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
router.navigateByUrl('/team/22/link');
|
||||
|
@ -2019,35 +2030,42 @@ describe('Integration', () => {
|
|||
expect(location.path()).toEqual('/team/22/simple?q=1#f');
|
||||
})));
|
||||
|
||||
it('should support history state',
|
||||
fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
describe('should support history and state', () => {
|
||||
let component: typeof LinkWithState|typeof DivLinkWithState;
|
||||
it('for anchor elements', () => {
|
||||
// Test logic in afterEach to reduce duplication
|
||||
component = LinkWithState;
|
||||
});
|
||||
|
||||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'link', component: LinkWithState}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
}]);
|
||||
it('for non-anchor elements', () => {
|
||||
// Test logic in afterEach to reduce duplication
|
||||
component = DivLinkWithState;
|
||||
});
|
||||
|
||||
router.navigateByUrl('/team/22/link');
|
||||
advance(fixture);
|
||||
afterEach(fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
const native = fixture.nativeElement.querySelector('a');
|
||||
expect(native.getAttribute('href')).toEqual('/team/22/simple');
|
||||
native.click();
|
||||
advance(fixture);
|
||||
router.resetConfig([{
|
||||
path: 'team/:id',
|
||||
component: TeamCmp,
|
||||
children: [{path: 'link', component}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
expect(fixture.nativeElement).toHaveText('team 22 [ simple, right: ]');
|
||||
router.navigateByUrl('/team/22/link');
|
||||
advance(fixture);
|
||||
|
||||
// Check the history entry
|
||||
const history = (location as any)._history;
|
||||
const native = fixture.nativeElement.querySelector('#link');
|
||||
native.click();
|
||||
advance(fixture);
|
||||
|
||||
expect(history[history.length - 1].state.foo).toBe('bar');
|
||||
expect(history[history.length - 1].state)
|
||||
.toEqual({foo: 'bar', navigationId: history.length});
|
||||
})));
|
||||
expect(fixture.nativeElement).toHaveText('team 22 [ simple, right: ]');
|
||||
|
||||
// Check the history entry
|
||||
const history = (location as any)._history;
|
||||
expect(history[history.length - 1].state)
|
||||
.toEqual({foo: 'bar', navigationId: history.length});
|
||||
})));
|
||||
});
|
||||
|
||||
it('should set href on area elements', fakeAsync(() => {
|
||||
@Component({
|
||||
|
@ -2232,7 +2250,9 @@ describe('Integration', () => {
|
|||
}
|
||||
}
|
||||
|
||||
beforeEach(() => { TestBed.configureTestingModule({providers: [AlwaysTrue]}); });
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({providers: [AlwaysTrue]});
|
||||
});
|
||||
|
||||
it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
@ -2253,7 +2273,9 @@ describe('Integration', () => {
|
|||
providers: [{
|
||||
provide: 'CanActivate',
|
||||
useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
|
||||
return Observable.create((observer: any) => { observer.next(false); });
|
||||
return Observable.create((observer: any) => {
|
||||
observer.next(false);
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
@ -2310,7 +2332,9 @@ describe('Integration', () => {
|
|||
TestBed.configureTestingModule({
|
||||
providers: [{
|
||||
provide: 'alwaysFalse',
|
||||
useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { return false; }
|
||||
useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
|
||||
return false;
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
@ -2330,7 +2354,6 @@ describe('Integration', () => {
|
|||
location.go('/two');
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/one');
|
||||
|
||||
})));
|
||||
});
|
||||
|
||||
|
@ -2368,12 +2391,16 @@ describe('Integration', () => {
|
|||
providers: [
|
||||
{
|
||||
provide: 'returnUrlTree',
|
||||
useFactory: (router: Router) => () => { return router.parseUrl('/redirected'); },
|
||||
useFactory: (router: Router) => () => {
|
||||
return router.parseUrl('/redirected');
|
||||
},
|
||||
deps: [Router]
|
||||
},
|
||||
{
|
||||
provide: 'returnRootUrlTree',
|
||||
useFactory: (router: Router) => () => { return router.parseUrl('/'); },
|
||||
useFactory: (router: Router) => () => {
|
||||
return router.parseUrl('/');
|
||||
},
|
||||
deps: [Router]
|
||||
}
|
||||
]
|
||||
|
@ -2381,7 +2408,7 @@ describe('Integration', () => {
|
|||
|
||||
it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const recordedEvents: any[] = [];
|
||||
let cancelEvent: NavigationCancel = null !;
|
||||
let cancelEvent: NavigationCancel = null!;
|
||||
router.events.forEach((e: any) => {
|
||||
recordedEvents.push(e);
|
||||
if (e instanceof NavigationCancel) cancelEvent = e;
|
||||
|
@ -2425,7 +2452,7 @@ describe('Integration', () => {
|
|||
it('works with root url',
|
||||
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const recordedEvents: any[] = [];
|
||||
let cancelEvent: NavigationCancel = null !;
|
||||
let cancelEvent: NavigationCancel = null!;
|
||||
router.events.forEach((e: any) => {
|
||||
recordedEvents.push(e);
|
||||
if (e instanceof NavigationCancel) cancelEvent = e;
|
||||
|
@ -2492,7 +2519,9 @@ describe('Integration', () => {
|
|||
{path: 'redirected', component: SimpleCmp}
|
||||
]);
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
router.navigateByUrl('/one').then(v => { resolvedPath = location.path(); });
|
||||
router.navigateByUrl('/one').then(v => {
|
||||
resolvedPath = location.path();
|
||||
});
|
||||
|
||||
tick();
|
||||
expect(resolvedPath).toBe('/redirected');
|
||||
|
@ -2541,7 +2570,8 @@ describe('Integration', () => {
|
|||
},
|
||||
{
|
||||
path: 'd/:param',
|
||||
component: WrapperCmp, runGuardsAndResolvers,
|
||||
component: WrapperCmp,
|
||||
runGuardsAndResolvers,
|
||||
children: [
|
||||
{
|
||||
path: 'e/:param',
|
||||
|
@ -2883,14 +2913,15 @@ describe('Integration', () => {
|
|||
{
|
||||
provide: 'RecordingDeactivate',
|
||||
useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
|
||||
log.push({path: a.routeConfig !.path, component: c});
|
||||
log.push({path: a.routeConfig!.path, component: c});
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
provide: 'alwaysFalse',
|
||||
useValue:
|
||||
(c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { return false; }
|
||||
useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
provide: 'alwaysFalseAndLogging',
|
||||
|
@ -2932,13 +2963,13 @@ describe('Integration', () => {
|
|||
expect(location.path()).toEqual('/team/22');
|
||||
|
||||
let successStatus: boolean = false;
|
||||
router.navigateByUrl('/team/33') !.then(res => successStatus = res);
|
||||
router.navigateByUrl('/team/33')!.then(res => successStatus = res);
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/team/33');
|
||||
expect(successStatus).toEqual(true);
|
||||
|
||||
let canceledStatus: boolean = false;
|
||||
router.navigateByUrl('/team/44') !.then(res => canceledStatus = res);
|
||||
router.navigateByUrl('/team/44')!.then(res => canceledStatus = res);
|
||||
advance(fixture);
|
||||
expect(location.path()).toEqual('/team/33');
|
||||
expect(canceledStatus).toEqual(false);
|
||||
|
@ -3143,11 +3174,12 @@ describe('Integration', () => {
|
|||
providers: [
|
||||
ClassWithNextState, {
|
||||
provide: 'FunctionWithNextState',
|
||||
useValue: (cmp: any, currentRoute: ActivatedRouteSnapshot,
|
||||
currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => {
|
||||
log.push(currentState.url, nextState.url);
|
||||
return true;
|
||||
}
|
||||
useValue:
|
||||
(cmp: any, currentRoute: ActivatedRouteSnapshot,
|
||||
currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => {
|
||||
log.push(currentState.url, nextState.url);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -3198,7 +3230,9 @@ describe('Integration', () => {
|
|||
}
|
||||
}
|
||||
|
||||
beforeEach(() => { TestBed.configureTestingModule({providers: [AlwaysTrue]}); });
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({providers: [AlwaysTrue]});
|
||||
});
|
||||
|
||||
it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
@ -3223,7 +3257,9 @@ describe('Integration', () => {
|
|||
providers: [{
|
||||
provide: 'CanDeactivate',
|
||||
useValue: (c: TeamCmp, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
|
||||
return Observable.create((observer: any) => { observer.next(false); });
|
||||
return Observable.create((observer: any) => {
|
||||
observer.next(false);
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
@ -3271,7 +3307,7 @@ describe('Integration', () => {
|
|||
|
||||
expect(location.path()).toEqual('/team/22');
|
||||
|
||||
router.navigateByUrl('/team/33') !.catch(() => {});
|
||||
router.navigateByUrl('/team/33')!.catch(() => {});
|
||||
advance(fixture);
|
||||
|
||||
expect(location.path()).toEqual('/team/22');
|
||||
|
@ -3282,7 +3318,6 @@ describe('Integration', () => {
|
|||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
@Component({selector: 'admin', template: '<router-outlet></router-outlet>'})
|
||||
class AdminComponent {
|
||||
}
|
||||
|
@ -3350,7 +3385,6 @@ describe('Integration', () => {
|
|||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
@Component({selector: 'lazy', template: 'lazy-loaded'})
|
||||
class LazyLoadedComponent {
|
||||
}
|
||||
|
@ -3418,7 +3452,6 @@ describe('Integration', () => {
|
|||
|
||||
it('should support navigating from within the guard',
|
||||
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([
|
||||
|
@ -3454,7 +3487,6 @@ describe('Integration', () => {
|
|||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
@Component({selector: 'lazy', template: 'lazy-loaded'})
|
||||
class LazyLoadedComponent {
|
||||
}
|
||||
|
@ -3477,21 +3509,23 @@ describe('Integration', () => {
|
|||
|
||||
let navFalseResult: any;
|
||||
let navTrueResult: any;
|
||||
router.navigateByUrl('/lazy-false').then(v => { navFalseResult = v; });
|
||||
router.navigateByUrl('/lazy-false').then(v => {
|
||||
navFalseResult = v;
|
||||
});
|
||||
advance(fixture);
|
||||
router.navigateByUrl('/lazy-true').then(v => { navTrueResult = v; });
|
||||
router.navigateByUrl('/lazy-true').then(v => {
|
||||
navTrueResult = v;
|
||||
});
|
||||
advance(fixture);
|
||||
|
||||
expect(navFalseResult).toBe(false);
|
||||
expect(navTrueResult).toBe(true);
|
||||
|
||||
})));
|
||||
|
||||
it('should execute CanLoad only once',
|
||||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
@Component({selector: 'lazy', template: 'lazy-loaded'})
|
||||
class LazyLoadedComponent {
|
||||
}
|
||||
|
@ -3526,10 +3560,11 @@ describe('Integration', () => {
|
|||
});
|
||||
|
||||
describe('order', () => {
|
||||
|
||||
class Logger {
|
||||
logs: string[] = [];
|
||||
add(thing: string) { this.logs.push(thing); }
|
||||
add(thing: string) {
|
||||
this.logs.push(thing);
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -3664,7 +3699,7 @@ describe('Integration', () => {
|
|||
tap(e => recordedEvents.push(e)),
|
||||
filter((e): e is NavigationStart => e instanceof NavigationStart), first());
|
||||
|
||||
navStart$.subscribe((e: NavigationStart | NavigationError) => {
|
||||
navStart$.subscribe((e: NavigationStart|NavigationError) => {
|
||||
router.navigate(
|
||||
['/blank'], {queryParams: {state: 'redirected'}, queryParamsHandling: 'merge'});
|
||||
advance(fixture);
|
||||
|
@ -3674,7 +3709,6 @@ describe('Integration', () => {
|
|||
advance(fixture);
|
||||
|
||||
expect(navigateSpy.calls.mostRecent().args[1].queryParams);
|
||||
|
||||
})));
|
||||
});
|
||||
|
||||
|
@ -3689,8 +3723,7 @@ describe('Integration', () => {
|
|||
children: [{
|
||||
path: 'link',
|
||||
component: DummyLinkCmp,
|
||||
children:
|
||||
[{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
}]
|
||||
}]);
|
||||
|
||||
|
@ -3745,8 +3778,7 @@ describe('Integration', () => {
|
|||
children: [{
|
||||
path: 'link',
|
||||
component: DummyLinkWithParentCmp,
|
||||
children:
|
||||
[{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
}]
|
||||
}]);
|
||||
|
||||
|
@ -3774,8 +3806,7 @@ describe('Integration', () => {
|
|||
children: [{
|
||||
path: 'link',
|
||||
component: DummyLinkCmp,
|
||||
children:
|
||||
[{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]
|
||||
}]
|
||||
}]);
|
||||
|
||||
|
@ -3831,7 +3862,6 @@ describe('Integration', () => {
|
|||
advance(fixture);
|
||||
expect(paragraph.textContent).toEqual('false');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('lazy loading', () => {
|
||||
|
@ -3934,8 +3964,8 @@ describe('Integration', () => {
|
|||
expect(location.path()).toEqual('/lazy/parent/child');
|
||||
expect(fixture.nativeElement).toHaveText('parent[child]');
|
||||
|
||||
const pInj = fixture.debugElement.query(By.directive(Parent)).injector !;
|
||||
const cInj = fixture.debugElement.query(By.directive(Child)).injector !;
|
||||
const pInj = fixture.debugElement.query(By.directive(Parent)).injector!;
|
||||
const cInj = fixture.debugElement.query(By.directive(Child)).injector!;
|
||||
|
||||
expect(pInj.get('moduleName')).toEqual('parent');
|
||||
expect(pInj.get('fromParent')).toEqual('from parent');
|
||||
|
@ -3989,7 +4019,9 @@ describe('Integration', () => {
|
|||
})
|
||||
class LoadedModule {
|
||||
static instances = 0;
|
||||
constructor() { LoadedModule.instances++; }
|
||||
constructor() {
|
||||
LoadedModule.instances++;
|
||||
}
|
||||
}
|
||||
|
||||
loader.stubbedModules = {expected: LoadedModule};
|
||||
|
@ -4121,7 +4153,7 @@ describe('Integration', () => {
|
|||
router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]);
|
||||
|
||||
let recordedError: any = null;
|
||||
router.navigateByUrl('/lazy/loaded') !.catch(err => recordedError = err);
|
||||
router.navigateByUrl('/lazy/loaded')!.catch(err => recordedError = err);
|
||||
advance(fixture);
|
||||
expect(recordedError.message)
|
||||
.toEqual(
|
||||
|
@ -4178,7 +4210,6 @@ describe('Integration', () => {
|
|||
it('should allow lazy loaded module in named outlet',
|
||||
fakeAsync(inject(
|
||||
[Router, NgModuleFactoryLoader], (router: Router, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
@Component({selector: 'lazy', template: 'lazy-loaded'})
|
||||
class LazyComponent {
|
||||
}
|
||||
|
@ -4218,7 +4249,6 @@ describe('Integration', () => {
|
|||
it('should allow componentless named outlet to render children',
|
||||
fakeAsync(inject(
|
||||
[Router, NgModuleFactoryLoader], (router: Router, loader: SpyNgModuleFactoryLoader) => {
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([{
|
||||
|
@ -4269,7 +4299,7 @@ describe('Integration', () => {
|
|||
lazyService: LazyLoadedServiceDefinedInModule, // should be able to inject lazy service
|
||||
eager:
|
||||
EagerParentComponent // should use the injector of the location to create a parent
|
||||
) {}
|
||||
) {}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
@ -4360,7 +4390,7 @@ describe('Integration', () => {
|
|||
const recordedEvents: any[] = [];
|
||||
router.events.forEach(e => recordedEvents.push(e));
|
||||
|
||||
router.navigateByUrl('/lazy/loaded') !.catch(s => {});
|
||||
router.navigateByUrl('/lazy/loaded')!.catch(s => {});
|
||||
advance(fixture);
|
||||
|
||||
expect(location.path()).toEqual('/');
|
||||
|
@ -4469,16 +4499,15 @@ describe('Integration', () => {
|
|||
advance(fixture);
|
||||
|
||||
const config = router.config as any;
|
||||
const firstConfig = config[1]._loadedConfig !;
|
||||
const firstConfig = config[1]._loadedConfig!;
|
||||
|
||||
expect(firstConfig).toBeDefined();
|
||||
expect(firstConfig.routes[0].path).toEqual('LoadedModule1');
|
||||
|
||||
const secondConfig = firstConfig.routes[0]._loadedConfig !;
|
||||
const secondConfig = firstConfig.routes[0]._loadedConfig!;
|
||||
expect(secondConfig).toBeDefined();
|
||||
expect(secondConfig.routes[0].path).toEqual('LoadedModule2');
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
describe('custom url handling strategies', () => {
|
||||
|
@ -4528,9 +4557,8 @@ describe('Integration', () => {
|
|||
router.resetConfig([{
|
||||
path: 'include',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
children:
|
||||
[{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
const events: any[] = [];
|
||||
|
@ -4592,9 +4620,8 @@ describe('Integration', () => {
|
|||
router.resetConfig([{
|
||||
path: 'include',
|
||||
component: TeamCmp,
|
||||
children: [
|
||||
{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}
|
||||
]
|
||||
children:
|
||||
[{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}]
|
||||
}]);
|
||||
|
||||
const events: any[] = [];
|
||||
|
@ -4686,19 +4713,19 @@ describe('Integration', () => {
|
|||
stored: {[k: string]: DetachedRouteHandle} = {};
|
||||
|
||||
shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
||||
return route.routeConfig !.path === 'a';
|
||||
return route.routeConfig!.path === 'a';
|
||||
}
|
||||
|
||||
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {
|
||||
this.stored[route.routeConfig !.path !] = detachedTree;
|
||||
this.stored[route.routeConfig!.path!] = detachedTree;
|
||||
}
|
||||
|
||||
shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
||||
return !!this.stored[route.routeConfig !.path !];
|
||||
return !!this.stored[route.routeConfig!.path!];
|
||||
}
|
||||
|
||||
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
|
||||
return this.stored[route.routeConfig !.path !];
|
||||
return this.stored[route.routeConfig!.path!];
|
||||
}
|
||||
|
||||
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
||||
|
@ -4707,10 +4734,16 @@ describe('Integration', () => {
|
|||
}
|
||||
|
||||
class ShortLifecycle implements RouteReuseStrategy {
|
||||
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
|
||||
shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
}
|
||||
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
|
||||
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
|
||||
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null { return null; }
|
||||
shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
}
|
||||
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null {
|
||||
return null;
|
||||
}
|
||||
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
||||
if (future.routeConfig !== curr.routeConfig) {
|
||||
return false;
|
||||
|
@ -4804,7 +4837,9 @@ describe('Integration', () => {
|
|||
!!router.parseUrl(router.url).root.children['toolpanel']);
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void { this.subscription.unsubscribe(); }
|
||||
public ngOnDestroy(): void {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'tool-1-cmp', template: 'Tool 1 showing'})
|
||||
|
@ -4876,7 +4911,6 @@ describe('Testing router options', () => {
|
|||
});
|
||||
|
||||
describe('malformedUriErrorHandler', () => {
|
||||
|
||||
function malformedUriErrorHandler(e: URIError, urlSerializer: UrlSerializer, url: string) {
|
||||
return urlSerializer.parse('/error');
|
||||
}
|
||||
|
@ -4951,11 +4985,18 @@ class LinkWithQueryParamsAndFragment {
|
|||
|
||||
@Component({
|
||||
selector: 'link-cmp',
|
||||
template: `<a [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</a>`
|
||||
template: `<a id="link" [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</a>`
|
||||
})
|
||||
class LinkWithState {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'div-link-cmp',
|
||||
template: `<div id="link" [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</div>`
|
||||
})
|
||||
class DivLinkWithState {
|
||||
}
|
||||
|
||||
@Component({selector: 'simple-cmp', template: `simple`})
|
||||
class SimpleCmp {
|
||||
}
|
||||
|
@ -5078,7 +5119,9 @@ class OutletInNgIf {
|
|||
})
|
||||
class DummyLinkWithParentCmp {
|
||||
private exact: boolean;
|
||||
constructor(route: ActivatedRoute) { this.exact = (<any>route.snapshot.params).exact === 'true'; }
|
||||
constructor(route: ActivatedRoute) {
|
||||
this.exact = (<any>route.snapshot.params).exact === 'true';
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'cmp', template: ''})
|
||||
|
@ -5100,7 +5143,9 @@ class RootCmp {
|
|||
class RootCmpWithOnInit {
|
||||
constructor(private router: Router) {}
|
||||
|
||||
ngOnInit(): void { this.router.navigate(['one']); }
|
||||
ngOnInit(): void {
|
||||
this.router.navigate(['one']);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -5117,7 +5162,9 @@ class RootCmpWithNamedOutlet {
|
|||
|
||||
@Component({selector: 'throwing-cmp', template: ''})
|
||||
class ThrowingCmp {
|
||||
constructor() { throw new Error('Throwing Cmp'); }
|
||||
constructor() {
|
||||
throw new Error('Throwing Cmp');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -5155,6 +5202,7 @@ class LazyComponent {
|
|||
RelativeLinkCmp,
|
||||
DummyLinkWithParentCmp,
|
||||
LinkWithQueryParamsAndFragment,
|
||||
DivLinkWithState,
|
||||
LinkWithState,
|
||||
CollectParamsCmp,
|
||||
QueryParamsAndFragmentCmp,
|
||||
|
@ -5185,6 +5233,7 @@ class LazyComponent {
|
|||
RelativeLinkCmp,
|
||||
DummyLinkWithParentCmp,
|
||||
LinkWithQueryParamsAndFragment,
|
||||
DivLinkWithState,
|
||||
LinkWithState,
|
||||
CollectParamsCmp,
|
||||
QueryParamsAndFragmentCmp,
|
||||
|
@ -5217,6 +5266,7 @@ class LazyComponent {
|
|||
RelativeLinkCmp,
|
||||
DummyLinkWithParentCmp,
|
||||
LinkWithQueryParamsAndFragment,
|
||||
DivLinkWithState,
|
||||
LinkWithState,
|
||||
CollectParamsCmp,
|
||||
QueryParamsAndFragmentCmp,
|
||||
|
|
Loading…
Reference in New Issue