From 830a780cb3b8f043a0c904855ce86ddb83ac0f64 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Tue, 1 Nov 2016 12:11:42 -0700 Subject: [PATCH] fix(router): CanDeactivate receives a wrong component Closes #12592 --- modules/@angular/router/src/router.ts | 19 +++++++++++++++---- .../@angular/router/test/integration.spec.ts | 17 ++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index b06949ef5d..b45dcc2ad8 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -867,14 +867,25 @@ export class PreActivation { private deactiveRouteAndItsChildren( route: TreeNode, outlet: RouterOutlet): void { const prevChildren: {[key: string]: any} = nodeChildrenAsMap(route); + const r = route.value; forEach(prevChildren, (v: any, k: string) => { - const childOutlet = outlet ? outlet.outletMap._outlets[k] : null; - this.deactiveRouteAndItsChildren(v, childOutlet); + if (!r.component) { + this.deactiveRouteAndItsChildren(v, outlet); + } else if (!!outlet) { + this.deactiveRouteAndItsChildren(v, outlet.outletMap._outlets[k]); + } else { + this.deactiveRouteAndItsChildren(v, null); + } }); - const component = outlet && outlet.isActivated ? outlet.component : null; - this.checks.push(new CanDeactivate(component, route.value)); + if (!r.component) { + this.checks.push(new CanDeactivate(null, r)); + } else if (outlet && outlet.isActivated) { + this.checks.push(new CanDeactivate(outlet.component, r)); + } else { + this.checks.push(new CanDeactivate(null, r)); + } } private runCanActivate(future: ActivatedRouteSnapshot): Observable { diff --git a/modules/@angular/router/test/integration.spec.ts b/modules/@angular/router/test/integration.spec.ts index 9a29ec9b95..9f5fbea00c 100644 --- a/modules/@angular/router/test/integration.spec.ts +++ b/modules/@angular/router/test/integration.spec.ts @@ -1245,7 +1245,7 @@ describe('Integration', () => { { provide: 'RecordingDeactivate', useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - log.push(['Deactivate', a.routeConfig.path]); + log.push({path: a.routeConfig.path, component: c}); return true; } }, @@ -1290,7 +1290,11 @@ describe('Integration', () => { children: [{ path: 'child', canDeactivate: ['RecordingDeactivate'], - children: [{path: 'simple', component: SimpleCmp}] + children: [{ + path: 'simple', + component: SimpleCmp, + canDeactivate: ['RecordingDeactivate'] + }] }] }] }, @@ -1304,9 +1308,12 @@ describe('Integration', () => { router.navigateByUrl('/simple'); advance(fixture); - expect(log).toEqual([ - ['Deactivate', 'child'], ['Deactivate', 'parent'], ['Deactivate', 'grandparent'] + const child = fixture.debugElement.children[1].componentInstance; + + expect(log.map((a: any) => a.path)).toEqual([ + 'simple', 'child', 'parent', 'grandparent' ]); + expect(log.map((a: any) => a.component)).toEqual([child, null, null, null]); }))); it('works with aux routes', @@ -1333,7 +1340,7 @@ describe('Integration', () => { router.navigate(['two-outlets', {outlets: {aux: null}}]); advance(fixture); - expect(log).toEqual([['Deactivate', 'b']]); + expect(log.map((a: any) => a.path)).toEqual(['b']); expect(location.path()).toEqual('/two-outlets/(a)'); })));