Sitelet https://github.com/angular/angular/commit/771f731
Skip to content

Commit 771f731

Browse files
zbirkenbueljosephperrott
authored andcommitted
fix(router): update getRouteGuards to check if the context outlet is activated (#39049)
In certain circumstances (errors during component constructor) the router outlet may not be activated before redirecting to a new route. If the new route requires running guards and resolvers the current logic will throw when accessing outlet.component due to an isActivated check within the property getter. This update brings the logic inline with deactivateRouterAndItsChildren, namely checking outlet.isActivated before trying to access outlet.component. Fixes #39030 PR Close #39049
1 parent 5d584b7 commit 771f731

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

‎packages/router/src/utils/preactivation.ts‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,8 @@ function getRouteGuards(
121121
getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
122122
}
123123

124-
if (shouldRun) {
125-
const component = context && context.outlet && context.outlet.component || null;
126-
checks.canDeactivateChecks.push(new CanDeactivate(component, curr));
124+
if (shouldRun && context && context.outlet && context.outlet.isActivated) {
125+
checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
127126
}
128127
} else {
129128
if (curr) {

‎packages/router/test/integration.spec.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3027,6 +3027,13 @@ describe('Integration', () => {
30273027
resolve: {data: 'resolver'},
30283028
},
30293029
]
3030+
},
3031+
{
3032+
path: 'throwing',
3033+
runGuardsAndResolvers,
3034+
component: ThrowingCmp,
3035+
canActivate: ['guard'],
3036+
resolve: {data: 'resolver'}
30303037
}
30313038
]);
30323039

@@ -3125,6 +3132,15 @@ describe('Integration', () => {
31253132
advance(fixture);
31263133
expect(guardRunCount).toEqual(5);
31273134
expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}, {data: 4}]);
3135+
3136+
// Issue #39030, always running guards and resolvers should not throw
3137+
// when navigating away from a component with a throwing constructor.
3138+
expect(() => {
3139+
router.navigateByUrl('/throwing').catch(() => {});
3140+
advance(fixture);
3141+
router.navigateByUrl('/a;p=1');
3142+
advance(fixture);
3143+
}).not.toThrow();
31283144
})));
31293145

31303146
it('should rerun rerun guards and resolvers when path params change',

0 commit comments

Comments
 (0)