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
?
The differencescanActivateChild will always be executed while navigating to/between child routes. For example, if we're at a child route child/1 and we navigate to child/2 , the guard will get executed. If we directly navigate to a child route, the guard will also get called.
Well, there is a difference, the canActivate exists to prevent unauthorized users from accessing a route, while canLoad is used to prevent the application from loading an entire module or component in a lazy way (lazy loading) if the user is not authorized.
CanActivate - Decides if a route can be activated. CanActivateChild - Decides if children routes of a route can be activated. CanDeactivate - Decides if a route can be deactivated. CanLoad - Decides if a module can be loaded lazily.
That is called AuthGuard. AuthGuard is used to protect the routes from unauthorized access.
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.
/admin
canActivate
is checked/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.
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 } ] } ] } ])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With