What are route guards in Angular?
Angular route guards are interfaces that can be implemented to control navigation to or away from routes. They provide a powerful way to manage access to different parts of your application based on various conditions, such as user authentication status, authorization roles, or whether data needs to be pre-fetched.
What are Route Guards?
Route guards are a feature in Angular's router that allows you to control navigation based on specific conditions. They prevent unauthorized access to routes, block users from leaving a route with unsaved changes, or even pre-fetch data before a component is activated. They essentially act as 'gatekeepers' for your application's routes.
Types of Route Guards
Angular provides several interfaces that you can implement to create different types of route guards, each serving a specific purpose in the navigation lifecycle.
- CanActivate: Determines if a route can be activated (i.e., if the user can navigate to it). Useful for authentication and authorization.
- CanActivateChild: Determines if the children of a route can be activated. Applies to child routes.
- CanDeactivate: Determines if a user can leave a route. Useful for preventing users from navigating away with unsaved changes.
- Resolve: Pre-fetches data before a route is activated, ensuring that the component has all necessary data upon initialization.
- CanLoad: Determines if a lazy-loaded module can be loaded. Prevents loading of modules that the user doesn't have access to.
Implementing a Route Guard
To create a route guard, you define a class that implements one or more of the guard interfaces. The guard's method (e.g., canActivate for CanActivate) must return a boolean, UrlTree, Observable<boolean | UrlTree>, or Promise<boolean | UrlTree>.
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service'; // Assume this service exists
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.authService.isLoggedIn()) {
return true; // User is logged in, allow access
} else {
// User is not logged in, redirect to login page
return this.router.createUrlTree(['/login']);
}
}
}
Once defined, you apply the guard to a route configuration in your app-routing.module.ts or feature module routing files using the canActivate (or canActivateChild, canDeactivate, resolve, canLoad) property.
import { Routes } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard] // Apply the AuthGuard here
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
canLoad: [AuthGuard] // Apply to lazy-loaded module
},
// ... other routes
];
Common Use Cases
- Authentication: Ensuring only logged-in users can access certain routes (e.g., a dashboard or profile page).
- Authorization: Checking if a user has the necessary roles or permissions to view a specific resource (e.g., an admin panel).
- Preventing Unsaved Changes: Prompting users before they navigate away from a form with unsaved data.
- Data Pre-fetching: Loading necessary data from a backend service before a component is even rendered, ensuring a smooth user experience.
- Lazy Loading Control: Preventing the loading of entire modules if the user isn't authorized to access any of its routes.