From e20cfe1bbc0fc2e95d83f2730f0a6e222ea617db Mon Sep 17 00:00:00 2001 From: Roy Ling Date: Sat, 1 Apr 2017 09:13:15 +0800 Subject: [PATCH] fix(router): canDeactivate guards should run from bottom to top Closes #15657. --- packages/router/src/router.ts | 12 ++++++---- packages/router/test/integration.spec.ts | 30 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 8ea9a118e2..4c61c68fc7 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -839,11 +839,10 @@ export class PreActivation { // reusing the node if (curr && future._routeConfig === curr._routeConfig) { - if (this.shouldRunGuardsAndResolvers( - curr, future, future._routeConfig !.runGuardsAndResolvers)) { + const shouldRunGuardsAndResolvers = this.shouldRunGuardsAndResolvers( + curr, future, future._routeConfig !.runGuardsAndResolvers); + if (shouldRunGuardsAndResolvers) { this.canActivateChecks.push(new CanActivate(futurePath)); - const outlet = context !.outlet !; - this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr)); } else { // we need to set the data future.data = curr.data; @@ -859,6 +858,11 @@ export class PreActivation { } else { this.traverseChildRoutes(futureNode, currNode, parentContexts, futurePath); } + + if (shouldRunGuardsAndResolvers) { + const outlet = context !.outlet !; + this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr)); + } } else { if (curr) { this.deactivateRouteAndItsChildren(currNode, context); diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index d73be5fef8..1168e14b7a 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -2435,6 +2435,11 @@ describe('Integration', () => { provide: 'canDeactivate_team', useFactory: (logger: Logger) => () => (logger.add('canDeactivate_team'), true), deps: [Logger] + }, + { + provide: 'canDeactivate_simple', + useFactory: (logger: Logger) => () => (logger.add('canDeactivate_simple'), true), + deps: [Logger] } ] }); @@ -2468,6 +2473,31 @@ describe('Integration', () => { 'canDeactivate_team', 'canActivateChild_parent', 'canActivate_team' ]); }))); + + it('should call deactivate guards from bottom to top', + fakeAsync(inject( + [Router, Location, Logger], (router: Router, location: Location, logger: Logger) => { + const fixture = createRoot(router, RootCmp); + + router.resetConfig([{ + path: '', + children: [{ + path: 'team/:id', + canDeactivate: ['canDeactivate_team'], + children: + [{path: '', component: SimpleCmp, canDeactivate: ['canDeactivate_simple']}], + component: TeamCmp + }] + }]); + + router.navigateByUrl('/team/22'); + advance(fixture); + + router.navigateByUrl('/team/33'); + advance(fixture); + + expect(logger.logs).toEqual(['canDeactivate_simple', 'canDeactivate_team']); + }))); }); });