M Nouman
M Nouman

Reputation: 591

Activate Angular guard for both parent and child nested module routes

I'm working with Nested Module Structure and having some difficulty to implement guard.

Right Now I have to use canActivate on parent module route and canActivateChild on every child module route.
I want a solution where I will just put guard on Parent module route and that guard will also be activated on all the child module routes...

Following is the module structure

app-routing.module.ts

{
    path: 'pages',
    loadChildren: () => PagesModule,
  },

pages-routing.module.ts canActivate on AdminModule route.

{
    path: 'admin',
    loadChildren: () => AdminModule,
    canActivate: [AuthGuard],
  },

admin-routing.module.ts canActivateChild on every child module of admin

{
    path: 'dashboard',
    loadChildren: () => DashboardModule,
    canActivateChild: [AuthGuard],
  },
  {
    path: 'allusers',
    loadChildren: () => AllUsersModule,
    canActivateChild: [AuthGuard],
  },

dashboard-routing.module.ts

const routes: Routes = [{ path: '', component: DashboardComponent }];

allusers-routing.module.ts

const routes: Routes = [{ path: '', component: AllUsersComponent }];

AuthGaurd

export class AuthGuard implements CanActivate, CanActivateChild {
  constructor(
    private readonly authService: AuthService,
    private readonly route: Router,
  ) {}

  async canActivate() {
    if (this.authService.isLoggedOut()) {
      localStorage.clear();
      this.route.navigate(['/login']);
      alert('Access Denied Token Not Found');
      return false;
    } else {
      return true;
    }
  }

  canActivateChild(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ):
    | boolean
    | UrlTree
    | Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree> {
    return this.canActivate();
  }
}

Upvotes: 1

Views: 2286

Answers (1)

Dzinx
Dzinx

Reputation: 57794

Your question doesn't state this explicitly, but I'm going to assume that you want AuthGuard to execute on every child route of admin/ (in your example, these will be pages/admin/dashboard and pages/admin/allusers).

In this case, it seems that you confused canActivate with canActivateChild.

If you define pages-routing.module.ts like so:

  {
    path: 'admin',
    loadChildren: () => AdminModule,
    canActivate: [AuthGuard],      // fire for pages/admin page itself
    canActivateChild: [AuthGuard], // fire for every descendant
  },

then all routes that are descendants of pages/admin/ URL will fire AuthGuard on entry, every time navigation occurs into or within pages/admin/ URL tree. You don't need to add any canActivate or canActivateChild anywhere else in the routing configuration. Note that going to pages itself will not trigger AuthGuard.

Edit: added canActivate entry, too, since you wrote you want to guard pages/admin itself as well.

More generally, canActivateChild, when defined on route X/, will fire every time navigation occurs whose target is a descendant of route X/, but not route X itself.

Upvotes: 0

Related Questions