Introduction

Route Guards in Angular are used to control access to routes in an application. They allow you to implement logic that determines whether a route can be activated, deactivated, loaded, or unloaded. This is particularly useful for authentication, authorization, and other conditional navigation scenarios.

Types of Route Guards

Angular provides several types of route guards:

  1. CanActivate: Determines if a route can be activated.
  2. CanActivateChild: Determines if a child route can be activated.
  3. CanDeactivate: Determines if a route can be deactivated.
  4. CanLoad: Determines if a module can be loaded lazily.
  5. Resolve: Pre-fetches data before activating a route.

Implementing CanActivate Guard

Step-by-Step Guide

  1. Create a Guard Service: Use Angular CLI to generate a guard service.

    ng generate guard auth
    
  2. Implement CanActivate Interface: Open the generated auth.guard.ts file and implement the CanActivate interface.

    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
    import { Observable } from 'rxjs';
    import { AuthService } from './auth.service'; // Assume you have an AuthService
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuard implements CanActivate {
    
      constructor(private authService: AuthService) {}
    
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.authService.isLoggedIn(); // Replace with your actual logic
      }
    }
    
  3. Register the Guard in Routes: Apply the guard to routes in your app-routing.module.ts.

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { AuthGuard } from './auth.guard';
    import { HomeComponent } from './home/home.component';
    import { LoginComponent } from './login/login.component';
    
    const routes: Routes = [
      { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
      { path: 'login', component: LoginComponent }
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    

Example: AuthService

Here is a simple example of an AuthService that the guard might use.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private loggedIn = false;

  login() {
    this.loggedIn = true;
  }

  logout() {
    this.loggedIn = false;
  }

  isLoggedIn(): boolean {
    return this.loggedIn;
  }
}

Practical Exercise

Task

  1. Create a new Angular project.
  2. Implement an AuthGuard that prevents access to a protected route unless the user is logged in.
  3. Create a simple login mechanism using AuthService.

Solution

  1. Create a new Angular project:

    ng new route-guards-demo
    cd route-guards-demo
    
  2. Generate AuthGuard:

    ng generate guard auth
    
  3. Implement AuthService:

    // auth.service.ts
    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthService {
      private loggedIn = false;
    
      login() {
        this.loggedIn = true;
      }
    
      logout() {
        this.loggedIn = false;
      }
    
      isLoggedIn(): boolean {
        return this.loggedIn;
      }
    }
    
  4. Implement AuthGuard:

    // auth.guard.ts
    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
    import { Observable } from 'rxjs';
    import { AuthService } from './auth.service';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuard implements CanActivate {
    
      constructor(private authService: AuthService) {}
    
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.authService.isLoggedIn();
      }
    }
    
  5. Set Up Routes:

    // app-routing.module.ts
    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { AuthGuard } from './auth.guard';
    import { HomeComponent } from './home/home.component';
    import { LoginComponent } from './login/login.component';
    
    const routes: Routes = [
      { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
      { path: 'login', component: LoginComponent }
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    
  6. Create Components:

    ng generate component home
    ng generate component login
    
  7. Implement Login Logic:

    // login.component.ts
    import { Component } from '@angular/core';
    import { AuthService } from '../auth.service';
    import { Router } from '@angular/router';
    
    @Component({
      selector: 'app-login',
      templateUrl: './login.component.html',
      styleUrls: ['./login.component.css']
    })
    export class LoginComponent {
    
      constructor(private authService: AuthService, private router: Router) {}
    
      login() {
        this.authService.login();
        this.router.navigate(['/home']);
      }
    }
    
    <!-- login.component.html -->
    <button (click)="login()">Login</button>
    
  8. Test the Application:

    • Start the application using ng serve.
    • Navigate to /home and verify that you are redirected to the login page if not logged in.
    • Log in and verify that you can access the home page.

Conclusion

Route Guards are a powerful feature in Angular that help you control access to routes based on custom logic. By implementing guards like CanActivate, you can ensure that only authorized users can access certain parts of your application. This module covered the basics of creating and using route guards, providing a solid foundation for more advanced routing scenarios.

© Copyright 2024. All rights reserved