question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Why resolves in routes executing after canActivate and canActivateChild?

See original GitHub issue

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 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:closed
  • Created 7 years ago
  • Comments:22 (2 by maintainers)

github_iconTop GitHub Comments

16reactions
xaraliscommented, Dec 5, 2017

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?

15reactions
SamuelMScommented, May 17, 2018

This generally defeats the purpose of route guards for async dependencies.

Imagine this use-case:

// loaded in the root app router
const appRoutes: Routes = [
    {
        path: '',
        resolve: {
            config: ConfigResolver,
            user: UserResolver,
        },
        children: [
            { path: 'error', component: ErrorComponent },
            {
                path: 'somewhere',
                loadChildren: 'app/somewhere/somewhere.module#SomewhereModule'
            },
            {
                path: 'elsewhere',
                loadChildren: 'app/elsewhere/elsewhere.module#ElsewhereModule'
            },
            { path: '**', redirectTo: 'somewhere' }
        ]
    },
    { path: '**', redirectTo: '' }
];

// loaded in a fictional "somewhere" router
const somewhereRoutes: Routes = [
    {
        path: '',
        resolve: {
            userWorkspace: UserWorkspaceResolver,
        },
        children: [
            {
                path: '',
                component: WorkspaceDetailComponent,
                canActivateChild: [ WorkspaceDetailGuard ],
                children: [
                    // ...
                ],
            },
            {
                path: 'onboarding',
                component: WorkspaceOnboardingComponent,
                canActivateChild: [ WorkspaceOnboardingGuard ],
                children: [
                    // ...
                ],
            },
            { path: '**', redirectTo: '' }
        ]
    },
    { path: '**', redirectTo: '' }
];

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular Resolve Vs Activate. CanActivate | by Janarthanan
CanActivate is an interface and shall used for authenticate the user and allow them conditionally access the route. CanActivate executes before Resolve.
Read more >
Route Guards — Angular. canActivate vs canActivateChild vs…
Guards are processed in the following order: canDeactivate; canLoad; canActivateChild; canActivate; resolve. I'm going to explain each type and ...
Read more >
CanActivate guards on child routes run before parent Resolve ...
Here, the parent resolver i.e. SiteResolver resolves after the child guard i.e. RouteGuard is invoked. What i want is SiteResolver to resolve ......
Read more >
Guards and Resolvers (in Angular) - Joel Kingsley
Both guards and resolvers are implemented the same way, that is by creating a class that implements the interface needed (i.e. CanActivate , ......
Read more >
Angular CanActivate vs Resolve - ConcretePage.com
Angular provides Resolve interface with resolve method declaration. To create a Angular Resolve guard, we need to create a class by implementing ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found