Angular: Guards y Resolvers

 

Guards y Resolvers en Angular

  • Guards: Son funciones o servicios que Angular utiliza para controlar el acceso a rutas específicas. Permiten ejecutar lógica antes de que una ruta se active o se desactive, asegurándose de que el usuario tenga permiso para navegar a esa ruta.

  • Resolvers: Son servicios que se utilizan para obtener datos antes de que una ruta se active. Permiten cargar datos necesarios para una vista antes de que se muestre, garantizando que todos los datos estén disponibles cuando el componente se carga.

Componentes de Guards y Resolvers en Angular

Guards:

  1. CanActivate: Se utiliza para decidir si una ruta se puede activar.
  2. CanActivateChild: Se utiliza para decidir si las rutas secundarias se pueden activar.
  3. CanDeactivate: Se utiliza para decidir si se puede salir de una ruta.
  4. CanLoad: Se utiliza para decidir si se puede cargar un módulo de manera diferida.

Resolvers:

  1. Resolve: Se utiliza para resolver datos antes de que una ruta se active.

....

Interpretación de cada componente

CanActivate:

Permite o deniega el acceso a una ruta.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable <boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    const isAuthenticated = false; // Aquí iría la lógica de autenticación
    if (isAuthenticated) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

 

CanActivateChild:

Similar a CanActivate, pero se aplica a rutas secundarias.

@Injectable({
  providedIn: 'root'
})
export class ChildGuard implements CanActivateChild {
  constructor(private router: Router) {}

  canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable <boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    const isAuthenticated = false; // Aquí iría la lógica de autenticación
    if (isAuthenticated) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

 

CanDeactivate:

Permite o deniega la salida de una ruta.

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

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

 

CanLoad:

Permite o deniega la carga de un módulo de manera diferida.

 @Injectable({
  providedIn: 'root'
})
export class CanLoadGuard implements CanLoad {
  constructor(private router: Router) {}

  canLoad(
    route: Route,
    segments: UrlSegment[]
  ): Observable <boolean> | Promise<boolean> | boolean {
    const isAuthenticated = false; // Aquí iría la lógica de autenticación
    if (isAuthenticated) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

 

Resolve:

Resuelve datos antes de que una ruta se active.

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable, of } 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();
  }
}

 

Código para Guards y Resolvers

  Con esta configuración, puedes proteger rutas específicas y cargar datos necesarios antes de que la ruta se active, utilizando Guards y Resolvers

1. Crear un Guard para Protección de Rutas

Crear el Guard de Autenticación:


// auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable <boolean> | Promise<boolean> | boolean {
    const isAuthenticated = false; // Aquí iría la lógica de autenticación
    if (isAuthenticated) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

 

Configurar el Guard en las Rutas:


// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'protected', loadChildren: () => import('./protected/protected.module').then(m => m.ProtectedModule), canActivate: [AuthGuard] }
];

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

 

2. Crear un Resolver para Cargar Datos Antes de la Activación de la Ruta

Crear el Servicio de Datos:


// data.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData(): Observable<any> {
    return of({ data: 'Resolved Data' });
  }
}

 

Crear el Resolver:


// data.resolver.ts
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();
  }
}

 

Configurar el Resolver en las Rutas:


// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { DataResolver } from './data.resolver';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'protected', loadChildren: () => import('./protected/protected.module').then(m => m.ProtectedModule), canActivate: [AuthGuard], resolve: { resolvedData: DataResolver } }
];

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

 

....

 

.:Encabezado

...comentario


Aquí va el código Javascript a mostrar en la entrada.

...comentario