Search code examples
angulartypescriptlazy-loadingangular-router-guards

How to implement Guard for components which are lazy loaded in Angular 16+


I am trying to trying to implement Guards for lazy loaded components. I have tried canMatch and canActivate for which I am getting the error.

Cannot match any routes. URL Segment: 'admin/home/all-users/658044f87bfc4f8d999c9464' Error: NG04002: Cannot match any routes.

When I try canActivateChild. I am able to reach the page as needed but I do not see any indication that Guard is being activated.

My routing is as follows:

App-routing.module.ts

 const routes: Routes = [
  { path: 'register', component: RegisterComponent },
  { path: 'login', component: LoginComponent },
  {
    path: 'dashboard/:id',
    canActivate: [authGuard],
    component: DashboardComponent,
  },
  { path: 'view', canActivate: [authGuard], component: ChatviewComponent },
  {
    path: 'group/:id',
    canActivate: [authGuard],
    component: GroupChatComponent,
  },
  {
    path: 'publichats/:id',
    canActivate: [authGuard],
    component: PublicChatsComponent,
  },
  {
    path: 'announcement/:id',
    canActivate: [authGuard],
    component: AnnouncementsComponent,
  },
  {
    path: '',
    children: [
      {
        path: 'admin',
        loadChildren: () =>
          import('./Admin/admin.module').then((mod) => mod.AdminModule),
      },
    ],
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

This is the Guard used here.

authgaurd.guard.ts

import { CanActivateFn, Router } from '@angular/router';

export const authGuard: CanActivateFn = (route, state) => {
  const routes:Router = new Router()
  const isAuth = localStorage.getItem("isAuthenticated");
  if (isAuth!==null){
    return true;
  }

  else{
    routes.navigate([''])
    return false;
  }

};

Theses are the routing of the child components:

admin-routing.module.ts

const routes: Routes = [
  {
    path:'header',
    component: HeaderBarComponent,
  },
  {
    path: 'login',
    component: AdminLoginComponent,
  },
  {
    path: 'dashboard/:id',
    component: DashComponent,
    canMatch:[authAdminGuard]
    // canActivate: [authAdminGuard]
  },

  {
    path: '',
    children: [
      {
        path: 'home',
        loadChildren: () =>
          import('./HomeComponents/home.module').then((mod) => mod.HomeModule),

      },
    ],
  },


];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})

home-routing.module.ts

const routes: Routes = [


  {
    path:'public-groups/:id',
    component:GroupsComponent,
    canMatch:[authAdminGuard]
  },
  {
    path:'all-users/:id',
    component:UsersComponent,
    canMatch:[authAdminGuard]
  },
  {
    path:'broadcast-channel/:id',
    component:BroadcastComponent,
    canMatch:[authAdminGuard]
  },
  {
    path:'user-profile/:id',
    component:UserProfileComponent,
    canMatch:[authAdminGuard]
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

The guard that I plan to use is as bellow:

authguard.guard.ts

import { CanActivateFn, Router } from '@angular/router';

export const authAdminGuard: CanActivateFn = (route, state) => {
  const routes:Router = new Router()
  const isAuth = localStorage.getItem("isAdminAuthenticated");
  if (isAuth)
      return true;
  else{
    routes.navigate(['/admin/login'])
    return false;
  }

};

Can someone please explain what has gone wrong?


Solution

  • Try updating route variable for app-routing.module.ts and admin-routing.ts.

    For app-routing.module.ts

     const routes: Routes = [
       //...
       {
         path: 'admin',
         loadChildren: () =>
         import('./Admin/admin.module').then((mod) => mod.AdminModule),
       },
       {
         path: '',
         redirectTo: 'admin',
         pathMatch: 'full'
       }
    ];
    

    For admin-routing.ts

    const routes: Routes = [
      //...
      {
        path: 'home',
        loadChildren: () =>
        import('./HomeComponents/home.module').then((mod) => mod.HomeModule),
      },
      {
        path: '',
        redirectTo: 'home',
        pathMatch: 'full'
      }
    
    ];
    

    You have to inject router for your guards instead simply create it:

    for authAdminGuard guard

    import { inject } from '@angular/core';
    import { CanActivateFn, Router } from '@angular/router';
    
    export const authAdminGuard: CanActivateFn = (route, state) => {
      const router: Router = inject(Router);
      const isAuth = localStorage.getItem("isAdminAuthenticated");
      if (isAuth)
        return true;
      else {
        routes.navigate(['/admin/login'])
        return false;
      }
    
    };
    

    Same change authGuard. Also check if these guards has been well provided in app.module.

    This should solve your issue.