From 44a7fae00f366e166592577a4c7beacfd86f3323 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 18 Mar 2021 09:10:22 -0700 Subject: [PATCH] fix(router): handle new navigations from a NavigationEnd event (#41262) This commit removes the line to set `currentNavigation` to `null` in the navigation transitions subscription of the router. This logic is already handled in the `finalize` stage of the transition pipe and has been found to cause issues if a new navigation is triggered from a subscription to the `NavigationEnd` event. fixes #37460 PR Close #41262 --- packages/router/src/router.ts | 1 - packages/router/test/bootstrap.spec.ts | 36 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 8c7a01f100..8fa4819b11 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -1293,7 +1293,6 @@ export class Router { .next(new NavigationEnd( t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree))); this.lastSuccessfulNavigation = this.currentNavigation; - this.currentNavigation = null; t.resolve(true); }, e => { diff --git a/packages/router/test/bootstrap.spec.ts b/packages/router/test/bootstrap.spec.ts index e3b9a63915..5abe19e4a7 100644 --- a/packages/router/test/bootstrap.spec.ts +++ b/packages/router/test/bootstrap.spec.ts @@ -18,6 +18,10 @@ describe('bootstrap', () => { let log: any[] = []; let testProviders: any[] = null!; + @Component({template: 'simple'}) + class SimpleCmp { + } + @Component({selector: 'test-app', template: 'root '}) class RootCmp { constructor() { @@ -394,4 +398,36 @@ describe('bootstrap', () => { expect(window.removeEventListener).toHaveBeenCalledWith('popstate', jasmine.any(Function)); expect(window.removeEventListener).toHaveBeenCalledWith('hashchange', jasmine.any(Function)); }); + + it('can schedule a navigation from the NavigationEnd event #37460', async (done) => { + @NgModule({ + imports: [ + BrowserModule, + RouterModule.forRoot( + [ + {path: 'a', component: SimpleCmp}, + {path: 'b', component: SimpleCmp}, + ], + ) + ], + declarations: [RootCmp, SimpleCmp], + bootstrap: [RootCmp], + providers: [...testProviders], + }) + class TestModule { + } + + const res = await platformBrowserDynamic([]).bootstrapModule(TestModule); + const router = res.injector.get(Router); + router.events.subscribe(() => { + expect(router.getCurrentNavigation()?.id).toBeDefined(); + }); + router.events.subscribe(async (e) => { + if (e instanceof NavigationEnd && e.url === '/b') { + await router.navigate(['a']); + done(); + } + }); + await router.navigateByUrl('/b'); + }); });