fix(router): shouldn't execute CanLoad when a route has been loaded

Closes #14475
Closes #15438
This commit is contained in:
Dzmitry Shylovich 2017-03-24 01:59:17 +03:00 committed by Victor Berchet
parent fb1be83a1b
commit 8785b2bf6d
2 changed files with 55 additions and 8 deletions

View File

@ -293,12 +293,14 @@ class ApplyRedirects {
} }
if (route.loadChildren) { if (route.loadChildren) {
if ((<any>route)._loadedConfig !== void 0) {
return of ((<any>route)._loadedConfig);
}
return mergeMap.call(runCanLoadGuard(ngModule.injector, route), (shouldLoad: boolean) => { return mergeMap.call(runCanLoadGuard(ngModule.injector, route), (shouldLoad: boolean) => {
if (shouldLoad) { if (shouldLoad) {
return (<any>route)._loadedConfig ? return map.call(
of ((<any>route)._loadedConfig) :
map.call(
this.configLoader.load(ngModule.injector, route), (cfg: LoadedRouterConfig) => { this.configLoader.load(ngModule.injector, route), (cfg: LoadedRouterConfig) => {
(<any>route)._loadedConfig = cfg; (<any>route)._loadedConfig = cfg;
return cfg; return cfg;

View File

@ -2075,7 +2075,9 @@ describe('Integration', () => {
}); });
describe('CanLoad', () => { describe('CanLoad', () => {
let canLoadRunCount = 0;
beforeEach(() => { beforeEach(() => {
canLoadRunCount = 0;
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
{provide: 'alwaysFalse', useValue: (a: any) => false}, {provide: 'alwaysFalse', useValue: (a: any) => false},
@ -2087,7 +2089,13 @@ describe('Integration', () => {
}, },
deps: [Router], deps: [Router],
}, },
{provide: 'alwaysTrue', useValue: (a: any) => true}, {
provide: 'alwaysTrue',
useValue: () => {
canLoadRunCount++;
return true;
}
},
] ]
}); });
}); });
@ -2173,6 +2181,43 @@ describe('Integration', () => {
[NavigationStart, '/blank'], [RoutesRecognized, '/blank'], [NavigationEnd, '/blank'] [NavigationStart, '/blank'], [RoutesRecognized, '/blank'], [NavigationEnd, '/blank']
]); ]);
}))); })));
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 {
}
@NgModule({
declarations: [LazyLoadedComponent],
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])]
})
class LazyLoadedModule {
}
loader.stubbedModules = {lazy: LazyLoadedModule};
const fixture = createRoot(router, RootCmp);
router.resetConfig([{path: 'lazy', canLoad: ['alwaysTrue'], loadChildren: 'lazy'}]);
router.navigateByUrl('/lazy/loaded');
advance(fixture);
expect(location.path()).toEqual('/lazy/loaded');
expect(canLoadRunCount).toEqual(1);
router.navigateByUrl('/');
advance(fixture);
expect(location.path()).toEqual('/');
router.navigateByUrl('/lazy/loaded');
advance(fixture);
expect(location.path()).toEqual('/lazy/loaded');
expect(canLoadRunCount).toEqual(1);
})));
}); });
describe('order', () => { describe('order', () => {