Alessandro Celeghin
Alessandro Celeghin

Reputation: 4189

canActivateChild is called multiple times

In my angular 5 project I "protect" some views based on the logged user role, so in my routing module I have:

    path: '',
    component: AdminLayoutComponent,
    canActivate: [AuthGuard],
    canActivateChild: [RoleGuard],
    children: [
      {
        path: '',
        loadChildren: './dashboard/dashboard.module#DashboardModule',
        data: { roles: ['role.all'] }
      },
      {
        path: 'checkPoints',
        loadChildren: './check-points/check-point-list/check-point-list.module#CheckpointListModule',
        data: { roles: ['role.admin', 'role.tech', 'role.backoffice'] }
      }...

AuthGuard check if the user is authenticated, and then RoleGuard check if the logged user has the role to see the page. But I see the canActivateChild method called multiple times when I try to navigate into child routes (2-3 times)

Is it correct behaviour?

Upvotes: 3

Views: 3081

Answers (2)

minigeek
minigeek

Reputation: 3166

So something similar case happened to me. I am sharing here if it helps someone. More of a theoretical solution.

Above @Fateme Fazli's answer shows exact correct architecture in which it should be passed but still it would be called twice. Here is how to properly compute your checks in the 2nd run, skipping 1st.

TL;DR

It happens because despite you put a canActivateChild outside in parent.route.module.ts where we use loadChildren() => ... syntax; there is still one more individual route.module.t of child in which another routes object is defined with '' i.e empty path. So for Me, route.data was coming as undefined in 1st go, but actual data in 2nd go.

There are 2 solutions

  1. Add canActivate guard on inner most individual route.module.ts (too much headache to add-in call children routes)
  2. Add canActivateChild on parent one and and inside canActivateChild() method if route.data is undefined, by default return true. 2nd time it comes, it will properly validate. if 1st run would be undefined it would never check 2nd run.

Here I only talked about 1 level of nesting, imagine having 4 levels of nesting, and the guard is applied somewhere outside, it will be called for all those nested children.

Upvotes: 3

Lia
Lia

Reputation: 11982

{
        path: "",
        component: AdminLayoutComponent,
        canActivate: [AuthGuard],
        children: [
            {
                path: "",
                canActivate: [RoleGuard],
                children: [
                    {
                      path: '',
                      loadChildren: './dashboard/dashboard.module#DashboardModule',
                      data: { roles: ['role.all'] }
      },...

i think this way would prevent 2-3 times.

Upvotes: 1

Related Questions