ChatGPT解决这个技术问题 Extra ChatGPT

CanActivate vs. CanActivateChild with component-less routes

The angular2 documentation about Route Guards left me unclear about when it is appropriate to use a CanActivate guards vs. a CanActivateChild guard in combination with component-less routes.

TL;DR: what's the point in having canActivateChild when I can use a component-less routes with canActivate to achieve the same effect?

Long version:

We can have multiple guards at every level of a routing hierarchy. The router checks the CanDeactivate and CanActivateChild guards first, from deepest child route to the top. Then it checks the CanActivate guards from the top down to the deepest child route.

I get that CanActivateChild is checked bottom up and CanActivate is checked top down. What doesn't make sense to me is the following example given in the docs:

@NgModule({    
  imports: [
    RouterModule.forChild([
      {
        path: 'admin',
        component: AdminComponent,
        canActivate: [AuthGuard],
        children: [
          {
            path: '',
            canActivateChild: [AuthGuard],
            children: [
              { path: 'crises', component: ManageCrisesComponent },
              { path: 'heroes', component: ManageHeroesComponent },
              { path: '', component: AdminDashboardComponent }
            ]
          }
        ]
      }
    ])
  ],
  exports: [
    RouterModule
  ]
})
export class AdminRoutingModule {}

So the admin path has a component-less route:

Looking at our child route under the AdminComponent, we have a route with a path and a children property but it's not using a component. We haven't made a mistake in our configuration, because we can use a component-less route.

Why is the code in this case inserting the AuthGuard in the child and in the root component (path admin)? Wouldn't is suffice to guard at the root?

I have created a plunkr based on the sample that removes the canActivateChild: [AuthGuard] and adds a logout button on the AdminDashboard. Sure enough, the canActivate of the parent route still guards, so what's the point in having canActivateChild when I can use component-less routes with canActivate?

I am wondering about the same thing, any chance you post this on github ?
This is a same question, maybe help for you: stackoverflow.com/questions/42632154/…
I think you can still have one canActivateChild on the root admin path and that way you don't need the component-less route. The component-less method here I believe is used in the guide to demonstrate that we can even go further and group the children routes that are related in order to apply even more specialized guards on them.

M
Matej

From the docs:

As we learned about guarding routes with CanActivate, we can also protect child routes with the CanActivateChild guard. The CanActivateChild guard works similarly to the CanActivate guard, but the difference is its run before each child route is activated. We protected our admin feature module from unauthorized access, but we could also protect child routes within our feature module.

Here's a practical example:

navigating to /admin canActivate is checked You navigate between the children of /admin route, but canActivate isn't called because it protects /admin canActivateChild is called whenever changing between children of the route its defined on.

I hope this helps you, if still unclear, you can check specific functionality by adding guards debugging them.


but why not just put AuthGuard as CanActivateChild on AdminComponent directly. I don't understand what the benefit of adding the extra component-less route is?
i guess it's going to get changed somehow later in the framework. there's always simpler solutions.
P
Peter Li

In real world, I feel it is redundant to use the same guard for the parent and all its children.

For a better example, suppose you have roles for admin users (Edit/View), you can add a guard for "Edit" only tabs.

    RouterModule.forChild([
      {
        path: 'admin',
        component: AdminComponent,
        canActivate: [AuthGuard],  //1 - redirect to login page if not logged in
        children: [
          //View Access
          {
            ......
          },
          //Edit Access
          {
            path: '',
            canActivateChild: [EditGuard], //2 - display "you don't have Edit permission to access this page"
            children: [
              { path: 'crises', component: ManageCrisesComponent },
              { path: 'heroes', component: ManageHeroesComponent },
              { path: '', component: AdminDashboardComponent }
            ]
          }
        ]
      }
    ])

i don't think it's redundant. I think the first page load, canActivate and canActivate child will be called, but when navigating from one child to another child, canActivate isn't called but canActivateChild is called, for example to check if JWT is still valid or needs to be refreshed silently, just my hunch.
c
crystalw

I also confused the angular2's documentation about routeGuard. what's the difference between the CanActivate guard and CanActivateChild guard.

I have some findings,I hope this will help you.

in the auth-guard.service.ts file

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;

return this.checkLogin(url);
}

canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.canActivate(route, state);
}

because the canActivate method is called in the canActivateChild function. you can write a snippet of code that don't call the canActivate method in the canActivateChild function.


A
Alejandro Gianetti

One reason I can think of is timeouts.

I'm starting to work with Angular 2, using an authentication provider. This provider expires a session which has been idle for more than a certain amount of time.

In a common situation where you leave your computer logged in and your session expires, the next navigation you try MUST validate your current situation. If you are navigating between child routes, I think CanActivateChild is the guard that will detect the expired session, and trigger a redirect to login, while CanActivate won't trigger at all.

Disclaimer: This came from the top of my head, I haven't implemented it yet.


S
Simon_Weaver

What if you have 10 children defined.

Then canActivateChild only needs to go in one place if they all have a common requirement, as opposed to 10 canActivate on each child.


You can still use one canActivate on the component-less routes.
R
Ravid Goldenberg

TL;DR: CanActivate and CanActivateChild are not for a component-less route.

I believe the docs simply overlooked the needless of both guards in a component-less route, as the intention was simply to demonstrate the component-less route in a particular mile-stone of the docs and the the use of both guards in another.

The use of both guards can be very useful in specific scenarios, for example: An admin dashboard allowing login to see several components, like mailing, logging statistics, resource usage etc. - at this level the access is restricted by the CanActivate guard - when trying to navigate to each component the roles of each admin-user is checked by the CanActivateChild guard.