fix(router): avoid router initialization for non root components

closes #12338
closes #12814
This commit is contained in:
Michael Seemann 2016-10-16 20:33:50 +02:00 committed by Victor Berchet
parent 45ddd6ba78
commit 2a4bf9a0df
2 changed files with 98 additions and 3 deletions

View File

@ -7,8 +7,7 @@
*/ */
import {APP_BASE_HREF, HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common'; import {APP_BASE_HREF, HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, Compiler, Inject, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, OpaqueToken, Optional, Provider, SkipSelf, SystemJsNgModuleLoader} from '@angular/core'; import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, Compiler, ComponentRef, Inject, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, OpaqueToken, Optional, Provider, SkipSelf, SystemJsNgModuleLoader} from '@angular/core';
import {Route, Routes} from './config'; import {Route, Routes} from './config';
import {RouterLink, RouterLinkWithHref} from './directives/router_link'; import {RouterLink, RouterLinkWithHref} from './directives/router_link';
import {RouterLinkActive} from './directives/router_link_active'; import {RouterLinkActive} from './directives/router_link_active';
@ -268,7 +267,12 @@ export function rootRoute(router: Router): ActivatedRoute {
export function initialRouterNavigation( export function initialRouterNavigation(
router: Router, ref: ApplicationRef, preloader: RouterPreloader, opts: ExtraOptions) { router: Router, ref: ApplicationRef, preloader: RouterPreloader, opts: ExtraOptions) {
return () => { return (bootstrappedComponentRef: ComponentRef<any>) => {
if (bootstrappedComponentRef !== ref.components[0]) {
return;
}
router.resetRootComponentType(ref.componentTypes[0]); router.resetRootComponentType(ref.componentTypes[0]);
preloader.setUpPreloading(); preloader.setUpPreloading();
if (opts.initialNavigation === false) { if (opts.initialNavigation === false) {

View File

@ -0,0 +1,91 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {APP_BASE_HREF} from '@angular/common';
import {ApplicationRef, Component, NgModule} from '@angular/core';
import {TestBed, inject} from '@angular/core/testing';
import {DOCUMENT} from '@angular/platform-browser';
import {Router, RouterModule, Routes} from '@angular/router';
@Component({selector: 'app-root', template: ''})
export class AppRootComponent {
}
@Component({selector: 'bootstrappable-component', template: ''})
export class BootstrappableComponent {
}
export const appRoutes: Routes = [{path: '**', redirectTo: ''}];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
declarations: [AppRootComponent, BootstrappableComponent],
entryComponents: [AppRootComponent, BootstrappableComponent],
providers: [{provide: APP_BASE_HREF, useValue: '/'}]
})
export class RouterInitTestModule {
}
describe('RouterModule', () => {
describe('RouterInitializer', () => {
beforeEach(() => { TestBed.configureTestingModule({imports: [RouterInitTestModule]}); });
beforeEach(inject([DOCUMENT], function(doc: HTMLDocument) {
const elRootApp = doc.createElement('app-root');
doc.body.appendChild(elRootApp);
const elBootComp = doc.createElement('bootstrappable-component');
doc.body.appendChild(elBootComp);
}));
it('should not init router navigation listeners if a non root component is bootstrapped',
() => {
const appRef: ApplicationRef = TestBed.get(ApplicationRef);
const r: Router = TestBed.get(Router);
const spy = spyOn(r, 'resetRootComponentType').and.callThrough();
appRef.bootstrap(AppRootComponent);
expect(r.resetRootComponentType).toHaveBeenCalled();
spy.calls.reset();
appRef.bootstrap(BootstrappableComponent);
expect(r.resetRootComponentType).not.toHaveBeenCalled();
});
it('should reinit router navigation listeners if a previously bootstrapped root component is destroyed',
(done) => {
const appRef: ApplicationRef = TestBed.get(ApplicationRef);
const r: Router = TestBed.get(Router);
const spy = spyOn(r, 'resetRootComponentType').and.callThrough();
const compRef = appRef.bootstrap(AppRootComponent);
expect(r.resetRootComponentType).toHaveBeenCalled();
spy.calls.reset();
compRef.onDestroy(() => {
appRef.bootstrap(BootstrappableComponent);
expect(r.resetRootComponentType).toHaveBeenCalled();
done();
});
compRef.destroy();
});
});
});