diff --git a/aio/content/examples/ngmodule/src/index.3.html b/aio/content/examples/ngmodule/src/index.3.html
index 43da9f2a37..ec55dd984e 100644
--- a/aio/content/examples/ngmodule/src/index.3.html
+++ b/aio/content/examples/ngmodule/src/index.3.html
@@ -1,7 +1,7 @@
-
+
NgModule - Contact
diff --git a/packages/router/src/router_module.ts b/packages/router/src/router_module.ts
index 78fa920ae2..8ecec6aff7 100644
--- a/packages/router/src/router_module.ts
+++ b/packages/router/src/router_module.ts
@@ -218,14 +218,24 @@ export function provideRoutes(routes: Routes): any {
* The bootstrap is blocked until the initial navigation is complete.
* * 'disabled' - the initial navigation is not performed. The location listener is set up before
* the root component gets created.
+ * * 'legacy_enabled'- the initial navigation starts after the root component has been created.
+ * The bootstrap is not blocked until the initial navigation is complete. @deprecated
+ * * 'legacy_disabled'- the initial navigation is not performed. The location listener is set up
+ * after @deprecated
+ * the root component gets created.
+ * * `true` - same as 'legacy_enabled'. @deprecated since v4
+ * * `false` - same as 'legacy_disabled'. @deprecated since v4
*
* The 'enabled' option should be used for applications unless there is a reason to have
* more control over when the router starts its initial navigation due to some complex
* initialization logic. In this case, 'disabled' should be used.
*
+ * The 'legacy_enabled' and 'legacy_disabled' should not be used for new applications.
+ *
* @experimental
*/
-export type InitialNavigation = 'enabled' | 'disabled';
+export type InitialNavigation =
+ true | false | 'enabled' | 'disabled' | 'legacy_enabled' | 'legacy_disabled';
/**
* @whatItDoes Represents options to configure the router.
@@ -244,7 +254,7 @@ export interface ExtraOptions {
useHash?: boolean;
/**
- * Enables/Disables the initial navigation (enabled by default).
+ * Disables the initial navigation.
*/
initialNavigation?: InitialNavigation;
@@ -322,12 +332,14 @@ export class RouterInitializer {
const router = this.injector.get(Router);
const opts = this.injector.get(ROUTER_CONFIGURATION);
- if (opts.initialNavigation === 'disabled') {
+ if (this.isLegacyDisabled(opts) || this.isLegacyEnabled(opts)) {
+ resolve(true);
+
+ } else if (opts.initialNavigation === 'disabled') {
router.setUpLocationChangeListener();
resolve(true);
- } else if (
- opts.initialNavigation === 'enabled' || typeof opts.initialNavigation === 'undefined') {
+ } else if (opts.initialNavigation === 'enabled') {
router.hooks.afterPreactivation = () => {
// only the initial navigation should be delayed
if (!this.initNavigation) {
@@ -360,11 +372,26 @@ export class RouterInitializer {
return;
}
+ if (this.isLegacyEnabled(opts)) {
+ router.initialNavigation();
+ } else if (this.isLegacyDisabled(opts)) {
+ router.setUpLocationChangeListener();
+ }
+
preloader.setUpPreloading();
router.resetRootComponentType(ref.componentTypes[0]);
this.resultOfPreactivationDone.next(null !);
this.resultOfPreactivationDone.complete();
}
+
+ private isLegacyEnabled(opts: ExtraOptions): boolean {
+ return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true ||
+ opts.initialNavigation === undefined;
+ }
+
+ private isLegacyDisabled(opts: ExtraOptions): boolean {
+ return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false;
+ }
}
export function getAppInitializer(r: RouterInitializer) {
diff --git a/packages/router/test/bootstrap.spec.ts b/packages/router/test/bootstrap.spec.ts
index 61d718e583..1277345b87 100644
--- a/packages/router/test/bootstrap.spec.ts
+++ b/packages/router/test/bootstrap.spec.ts
@@ -90,6 +90,48 @@ describe('bootstrap', () => {
});
});
+ it('should NOT wait for resolvers to complete when initialNavigation = legacy_enabled',
+ (done) => {
+ @Component({selector: 'test', template: 'test'})
+ class TestCmpLegacyEnabled {
+ }
+
+ @NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forRoot(
+ [{path: '**', component: TestCmpLegacyEnabled, resolve: {test: TestResolver}}],
+ {useHash: true, initialNavigation: 'legacy_enabled'})
+ ],
+ declarations: [RootCmp, TestCmpLegacyEnabled],
+ bootstrap: [RootCmp],
+ providers: [...testProviders, TestResolver],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ })
+ class TestModule {
+ constructor(router: Router) {
+ log.push('TestModule');
+ router.events.subscribe(e => log.push(e.constructor.name));
+ }
+ }
+
+ platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
+ const router = res.injector.get(Router);
+ expect(router.routerState.snapshot.root.firstChild).toBeNull();
+ // ResolveEnd has not been emitted yet because bootstrap returned too early
+ expect(log).toEqual([
+ 'TestModule', 'RootCmp', 'NavigationStart', 'RoutesRecognized', 'GuardsCheckStart',
+ 'GuardsCheckEnd', 'ResolveStart'
+ ]);
+
+ router.events.subscribe((e) => {
+ if (e instanceof NavigationEnd) {
+ done();
+ }
+ });
+ });
+ });
+
it('should not run navigation when initialNavigation = disabled', (done) => {
@Component({selector: 'test', template: 'test'})
class TestCmpDiabled {
@@ -120,6 +162,37 @@ describe('bootstrap', () => {
});
});
+ it('should not run navigation when initialNavigation = legacy_disabled', (done) => {
+ @Component({selector: 'test', template: 'test'})
+ class TestCmpLegacyDisabled {
+ }
+
+ @NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forRoot(
+ [{path: '**', component: TestCmpLegacyDisabled, resolve: {test: TestResolver}}],
+ {useHash: true, initialNavigation: 'legacy_disabled'})
+ ],
+ declarations: [RootCmp, TestCmpLegacyDisabled],
+ bootstrap: [RootCmp],
+ providers: [...testProviders, TestResolver],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ })
+ class TestModule {
+ constructor(router: Router) {
+ log.push('TestModule');
+ router.events.subscribe(e => log.push(e.constructor.name));
+ }
+ }
+
+ platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
+ const router = res.injector.get(Router);
+ expect(log).toEqual(['TestModule', 'RootCmp']);
+ done();
+ });
+ });
+
it('should not init router navigation listeners if a non root component is bootstrapped',
(done) => {
@NgModule({