Why resolves in routes executing after canActivate and canActivateChild?
See original GitHub issueI’m submitting a … (check one with “x”)
[ ] bug report => search github for a similar issue or PR before submitting
[ x ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior Why resolves in routes executing after canActivate and canActivateChild? Some activate actions are based on the data returned by the calling in resolve. However, currently the canActivate and canActivateChild action will executed firstly before resolves. That is not reasonable, right?
Expected behavior
canActivate and canActivateChild action will executed after resolve returned.
Minimal reproduction of the problem with instructions
What is the motivation / use case for changing the behavior? Session check etc.
Please tell us about your environment: npm start
-
Angular version: 2.0.X 2.0.6
-
Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] All browsers where this could be reproduced
-
Language: [all] all
-
Node (for AoT issues):
node --version
=
v6.9.5
Issue Analytics
- State:
- Created 7 years ago
- Comments:22 (2 by maintainers)
This is totally flawed in case of children routes any time you develop something a little more complicated than just a todo list. Usually, you would expect guards/resolves in parent routes are already resolved, so you can access the data in children guards/resolves. Unfortunately, this sequence of (logical) behavior is not put in place with current Angular router. Instead, it is followed only with guards and not for resolvers.
This becomes a real pain in the ass if your child guards require something which should have been dealt with one level above in the route hierarchy like getting some record that has to be resolved (and available) for all the child routes.
Am I something missing?
This generally defeats the purpose of route guards for async dependencies.
Imagine this use-case:
Pretty simple. Two relevant modules: the root “app” module and a lazy-loaded “somewhere” module. Pardon the naming.
A bunch of top-level information is resolved at the highest-order routes, and then more information about some fictional “workspace” is resolved within the somewhere module.
Here’s the catch: the “WorkspaceDetailGuard” and “WorkspaceOnboardingGuard” guards are dependent on the workspace resolved at a parent route (via UserWorkspaceResolver), which in turn is dependent on the user data loaded even before then (via UserResolver).
Per the explanations in this thread, this will never work as-is, since guards (CanActivate, CanActivateChild, etc) are always processed before resolvers can even begin their work. This makes sense if you ask “why start loading data before we know the user can even activate XYZ route” – but only from a strictly synchronous standpoint; there’s no reason to assume users will have all the information they need to properly “guard” routes before they make any asynchronous calls.
So, the apparent solution from this issue is to convert all async guards to resolvers, and do work in them – or convert all resolvers to guards – so that they fire in hierarchical order and can properly depend on each other. But this is not intuitive at all from a segregation of duties standpoint: guards are meant to handle authorization, and resolvers load data. In either of these scenarios, you’re essentially using one or the other, but not both; you’ll have guards that load data, or you’ll have resolvers that handle authorization. This is backwards and is confusing.
Let me know if I’m misunderstanding something here; otherwise, I’d like to re-open this ticket and suggest that Angular handle guards first, then resolvers, but follow the parent -> child route hierarchy; in other words, guarantee that parent route data is resolved before child route logic fires.