One of the most useful features of an Angular application is the ability to manage route access with Angular Guards. They aid in application security by deciding whether or not a user can access a specific route. An in-depth explanation of angular guards, including their types, applications, and real-world examples, will be given in this article.

Angular Guard Types
Angular offers five different kinds of guards.

  • CanActivate: Ascertains the possibility of activating a route.
  • CanActivateChild: Ascertains whether it is possible to activate a child route.   
  • CanDeactivate: Ascertains if deactivating a route is possible.
  • Before a route is activated, resolve pre-fetches of data.
  • Checks whether a module can be loaded slowly using the CanLoad function.
1. Capabilities to Activate
To determine whether a route can be activated, utilize the CanActivate guard. It is frequently employed for permission and authentication needs.

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(
    private authService: AuthService,
    private router: Router
  ) {}

  canActivate(): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['login']);
      return false;
    }
  }
}


2. CanActivateChild

The CanActivateChild guard works similarly to CanActivate but is applied to child routes.
import { Injectable } from '@angular/core';
import { CanActivateChild, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class ChildAuthGuard implements CanActivateChild {

  constructor(private authService: AuthService, private router: Router) {}

  canActivateChild(): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['login']);
      return false;
    }
  }
}

3. CanDeactivate
The CanDeactivate guard is used to decide if a route can be exited. It is useful for prompting the user to save changes before navigating away from a form.
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable({
  providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(component: CanComponentDeactivate): Observable<boolean> | Promise<boolean> | boolean {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}


4. Resolve

The Resolve guard pre-fetches data before a route is activated, ensuring that the required data is available when the route is activated.
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { DataService } from './data.service';

@Injectable({
  providedIn: 'root'
})
export class DataResolver implements Resolve<any> {

  constructor(private dataService: DataService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    return this.dataService.getData();
  }
}

5. CanLoad
The CanLoad guard is used to determine if a module can be loaded lazily. It prevents the loading of modules if certain conditions are not met.
import { Injectable } from '@angular/core';
import { CanLoad, Route, UrlSegment, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
  providedIn: 'root'
})
export class CanLoadGuard implements CanLoad {

  constructor(
    private authService: AuthService,
    private router: Router
  ) {}

  canLoad(route: Route, segments: UrlSegment[]): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['login']);
      return false;
    }
  }
}


Implementing Guards in Routes
To use guards in your routes, you need to add them to the route configuration.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard';
import { ChildAuthGuard } from './child-auth.guard';
import { CanDeactivateGuard } from './can-deactivate.guard';
import { DataResolver } from './data.resolver';
import { CanLoadGuard } from './can-load.guard';
import { AdminComponent } from './admin/admin.component';  // Assuming you have this component
import { SettingsComponent } from './settings/settings.component';  // Assuming you have this component
import { FormComponent } from './form/form.component';  // Assuming you have this component

const routes: Routes = [
  {
    path: 'home',
    component: HomeComponent,
    canActivate: [AuthGuard],
    resolve: { data: DataResolver }
  },
  { path: 'login', component: LoginComponent },
  {
    path: 'admin',
    component: AdminComponent,
    canActivateChild: [ChildAuthGuard],
    children: [
      { path: 'settings', component: SettingsComponent }
    ]
  },
  {
    path: 'form',
    component: FormComponent,
    canDeactivate: [CanDeactivateGuard]
  },
  {
    path: 'lazy',
    loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule),
    canLoad: [CanLoadGuard]
  }
];

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

Conclusion
The management of access control in your apps requires the use of Angular Guards. They offer a method for effectively managing user rights and putting security checks into place. You may make sure that your application operates correctly in a variety of scenarios, including data pre-fetching, authorization, authentication, and avoiding unsaved changes, by utilizing the different kinds of guards. Implementing guards effectively can enhance the security and usability of your Angular application, making it robust and user-friendly.

Happy Coding!