Aller au contenu

C'est quoi un Guard ?

Un Guard permet d’autoriser ou non la navigation vers une route. Il existe plusieurs types de Guard dans Angular.

CanActivate

Un cas courant est une route qu’on ne peut accĂ©der que si on est connectĂ© Ă  l’application.

export function isLoggedInGuard(): CanActivateFn {
  return (route, state) => {
    const router = inject(Router);
    const isAuthenticated = inject(AuthService).isAuthenticated;

    if (isAuthenticated()) return true;
    return this.router.parseUrl("/login");
  };
}

Ici on a dĂ©finit un Guard qui vĂ©rifie si le user est connectĂ©, si c’est le cas on renvoie true donc on peut accĂ©der Ă  la route, sinon on retourne la route login ce qui annule la navigation prĂ©cĂ©dente et navigue vers la route login.

Il ne nous reste plus qu’à utiliser ce Guard dans une Route.

export const routes: Route[] = [
  {
    path: "profile",
    component: ProfileComponent,
    canActivate: [isLoggedInGuard],
  },
];

CanDeactivate

canDeactivate est l’inverse de canActivate. Il permet de vĂ©rifier si on peut quitter une route. Par exemple, si on a un formulaire non sauvegardĂ©, on pourrait vouloir afficher un message de confirmation avant de quitter la route.

export const canDeactivateFeedbackRouteGuard: CanDeactivateFn<FeedbackRoute> = (
  component: FeedbackRoute
) => {
  if (!component.formCompleted()) {
    return window.confirm("Are you sure you want to leave?");
  } else {
    return true;
  }
};

Ici, on vĂ©rifie si le formulaire est complĂ©tĂ©, si ce n’est pas le cas on demande une confirmation avant de quitter la route.

On utilise ce Guard de la mĂȘme maniĂšre que canActivate en le plaçant dans la route.

CanMatch

canMatch permet de vĂ©rifier si une route peut ĂȘtre activĂ©e, tout comme canActivate, mais si ce n’est pas le cas alors le router va essayer de matcher une autre route avec le mĂȘme path.

export function hasRoleGuard(role: Role): CanActivateFn {
  return (route, state) => {
    const role$ = inject(UserStore).role$:

    // actuellement ce role 👇 est 'student'
    return role$.pipe(map(userRole => userRole === role));
  };
}
export const appRoutes: Route[] = [
  {
    path: "room",
    loadComponent: () => import("./teachers-room.component"),
    // grĂące Ă  canMatch, le router va sauter ce path et essayer
    // le path 'room' suivant car 👇 renvoie false
    canMatch: [hasRoleGuard("teacher")],
  },
  {
    path: "room",
    loadComponent: () => import("./students-room.component"),
    // et ici, 👇 renvoie true donc 👆 va ĂȘtre chargĂ©
    canMatch: [hasRoleGuard("student")],
  },
];