Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 669
Johannes Rudolph Avatar asked Oct 20 '16 19:10

Johannes Rudolph


People also ask

What is the key difference between the canActivate and CanActivateChild guards?

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.

What is the difference between the canActivate and the CanLoad route guards?

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.

What is the difference between canActivate and CanDeactivate?

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.

Which route Guard is helpful in preventing Unauthorised access to a component?

That is called AuthGuard. AuthGuard is used to protect the routes from unauthorized access.


2 Answers

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:

  1. navigating to /admin
  2. canActivate is checked
  3. You navigate between the children of /admin route, but canActivate isn't called because it protects /admin
  4. 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.

like image 164
Matej Avatar answered Oct 15 '22 00:10

Matej


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 }             ]           }         ]       }     ]) 
like image 29
Peter Li Avatar answered Oct 15 '22 01:10

Peter Li