angular: Allow CanActivate[Child] Guards to be "blocking"
I’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 CanActivate[Child] Guards run, parent-first, in parallel, meaning there is no way to resolve data in a parent that may be needed in child guards, unless managed explicitly elsewhere.
Expected behavior A CanActivate[Child] guard’s behavior could possibly be set to block children guards from.
Minimal reproduction of the problem with instructions
{
path: 'parent',
canActivateChild: [FiveSecondObservableGuard], // Takes a long time
children: [
{
path: 'child',
component: ChildComponent, // waits a long time, as expected
canActivate: [AuthGuard] // Runs immediately
}
]
}
What is the motivation / use case for changing the behavior? Loading server information/flags that are required in all Guards can now be done in two ways:
- in
APP_INITIALIZER
, which severely hinders UX choices/flexibility - Making all requests for server data asynchronous, making the whole codebase needlessly complex.
When a certain branch of routes is behind an AuthGuard that may need asynchronous loading, while the components respect the Guard the Guards themselves (which may require user identification to be complete) won’t necessarily have access to that (unless all data is made asynchronous, as mentioned above)
-
Angular version: 2.0.X
-
Browser: all
-
Language: all
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 28
- Comments: 27 (2 by maintainers)
Has there been any progress on this? To me the way guards work right now is really limiting. They are only useful for the most simple of operations. Without this feature being implemented having any nested guards is difficult.
Imagine the very common scenario where you have a top level route with an AuthGuard applied. Various child routes then could have other guards that need to make service/API calls. To make those calls they would require an auth token which is not guaranteed because the parent AuthGuard may not be complete. This means in every single other guard now you have to wait on the same async work the parent AuthGuard is doing?
@vsavkin any updates on this? It seems like everyone forgot about this issue. Actually it should have a minimum of priority. Angular 4 still has this issue. Everyone (including me right now) ends up with ugly workarounds and bad behaviors in their apps because of this. Please discuss with other contributors and let’s find a solution ASAP.
Hello?
I hate to be the guy who behaves ugly here… But we are at year six of this feature request.
Angular has made massive improvements… Yet you still cannot use guards in applications that require top level logic to be run before nested guards get hit.
I cannot think of a single “production level” use case for the current guard logic.
PLEASE MAKE THIS A TOP PRIORITY
I’m running into the exact scenario that @k-schneider is describing. Really surprised that there doesn’t seem to be an answer for this. I have a top level component that manages setting up auth values needed for future guards and the child guards run before the parent can complete.
This was extremely easy to do using resolves in Angular 1.x with ui-router.
@es-lab I actually found (what appears to me as) a proper work around for this issue. In my case, some of the data I was trying to pull in through Guards were really more to do with application information. Through the use of
Resolvers
which are guaranteed to run after all of the guards are completed you can enforce the order of execution you need.It actually doesn’t appear to be a well document concept but you can enforce a resolver’s return using the following class declaration
export class ApprovedResolver implements Resolve<boolean> {
and then in the class implement a function with a corresponding signature
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
This blog post walks you through what you need to know to fully implement a Resolver.
any news ?
canLoad still have the same problem. I think it should wait for canActivate on the parent to finish, but it doesn’t.
This reminds me of ui-router resolution, is that where the inspiration comes from?
While it is a valid solution, making a Guard (not a resolution) blocking would mean not having to specify it in every subsequent child explicitly.