From e34299af256326366ef2176bd905d9a64158f2df 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) (#41511) 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 PR Close #41511 --- packages/router/src/router.ts | 1 - packages/router/test/bootstrap.spec.ts | 38 ++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index b18c7433d31..87f314b4e4f 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -1245,7 +1245,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 5c76c6b8e2c..589bdf83e4b 100644 --- a/packages/router/test/bootstrap.spec.ts +++ b/packages/router/test/bootstrap.spec.ts @@ -19,6 +19,10 @@ describe('bootstrap', () => { let log: any[] = []; let testProviders: any[] = null!; + @Component({template: 'simple'}) + class SimpleCmp { + } + @Component({selector: 'test-app', template: 'root '}) class RootCmp { constructor() { @@ -369,7 +373,35 @@ describe('bootstrap', () => { done(); }); - function waitForNavigationToComplete(router: Router): Promise { - return router.events.pipe(filter((e: any) => e instanceof NavigationEnd), first()).toPromise(); - } + 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'); + }); });