Guards

Son clases que nos permiten proteger rutas.

Al igual que los servicios, los guards se declaran en un módulo.

<!-- app.module.ts -->

@NgModule({
    ...
    providers: [AutenticacionGuard],
    ...
})

Los Guards deben implementar alguna de las siguientes cuatro interfaces:

- CanActivate

- CanActivateChild

- CanDeactivate

- CanLoad

CanActivate

CanActivate: Protege una ruta

<!-- autenticacion.guard.ts -->
...
export class AutenticadoGuard implements CanActivate {
	canActivate(
                rutaActivaFoto: ActivatedRouteSnapshot, 
                historialEstados: RouterStateSnapshot): 
                    Observable<boolean> | Promise<boolean> | boolean 
                {
		    return true
	        }
}
<!-- app.module.ts -->
...
const rutas: Route[] = [
    {
        path: "libros", 
        component: LibrosListadoComponent, 
        canActivate: [AutenticacionGuard]
    }
]

CanActivateChild

CanActivateChild: Protege las rutas hijas

<!-- autenticacion.guard.ts -->
...
export class AutenticadoGuard implements CanActivateChild {
	canActivateChild(
                rutaActivaFoto: ActivatedRouteSnapshot, 
                historialEstados: RouterStateSnapshot): 
                    Observable<boolean> | Promise<boolean> | boolean 
                {
		    return true
	        }
}
<!-- app.module.ts -->
...
const rutas: Route[] = [
    {
        path: "libros", 
        component: LibrosListadoComponent, 
        canActivate: [AutenticacionGuard],
        canActivateChild: [AutenticacionGuard],
        children: [
            {path: "edicion", component: LibrosEdicion}
        ]
    }
]

CanDeactivate

CanDeactivate: No protege rutas. Protege data no guardada.

<!-- guardado.guard.ts -->
...
interface canDeactivateComponent {
  canDeactivateComponente: () => boolean
}

@Injectable()
export class GuardadoGuard implements CanDeactivate<canDeactivateComponent> {
  canDeactivate(component: canDeactivateComponent): boolean {
    if(component.canDeactivateComponente()){
      if(confirm("Hay datos no salvados, ¿Quieres salvarlos?")){
        return false
      }

      return true
    }

    return true
  }

}
<!-- app.module.ts -->
...
const rutas: Route[] = [
    {
        path: "libros", 
        component: LibrosListadoComponent, 
        canActivate: [AutenticacionGuard],
        canActivateChild: [AutenticacionGuard],
        children: [
            {
                path: "edicion", 
                component: LibrosEdicion, 
                canDeactivate: [GuardadoGuard]
            }
        ]
    }
]

Enviando data a una ruta

<!-- app.module.ts -->
...
const rutas: Route[] = [
    {
        path: "libros", 
        component: LibrosListadoComponent, 
        data: {
            mensaje: "Mensaje enviado al componente"
        }
    }
]

Se enviada datos a un componente usando la propiedad "data"

<!-- libros-listado.component.ts -->
...
export class LibrosListadoComponent {
    constructor(private rutaActiva: ActivatedRoute) {}

    ngOnInit(){
        const mensaje = this.rutaActiva.snapshot.data["mensaje"]
    }
}

Para leer "data" desde un componente se usa la ruta activa.

Resolve

Es una clase que nos permite cargar data antes de cargar el componente

<!-- app.module.ts -->
...
const rutas: Route[] = [
    {
        path: "libros", 
        component: LibrosListadoComponent, 
        resolve: {
            info: DataResolve
        }
    }
]

Se enviada datos a un componente usando la propiedad "resolve"

Al igual que los servicios y los guards, se declaran en un módulo.

<!-- app.module.ts -->

@NgModule({
    ...
    providers: [DataResolve],
    ...
})
...
export class DataResolve implements Resolve<any> {

	resolve(
            rutaActiva: ActivatedRouteSnapshot, 
            historialEstados: RouterStateSnapshot): 
            Observable<any> | Promise<any> | any {
                return {usuario: "ABC"}
            }

}

Los Resolves implementan una interface que también se llama "Resolve"

<!-- libros-listado.component.ts -->
...
export class LibrosListadoComponent {
    constructor(private rutaActiva: ActivatedRoute) {}

    ngOnInit(){
        const datos = this.rutaActiva.snapshot.data["info"]
    }
}

Para leer desde un "Resolve" se hace de manera similar a "Data".

useHash

"useHash" nos permite indicar si las rutas que aparecerán en el navegador usarán "#" o no.

Para indicar su uso, hay que agregarlo al manejador de rutas.

<!-- app.routing.module.ts -->
...
@NgModule({
    ...
    imports: [
        RouterModule.forRoot(rutas, {useHash: true})
    ]
    ...
})
...

queryParamsHandling

"queryParamsHandling" sirve para indicar si los parámetros de querystring se mantienen o si se suman nuevos parámetros de querystring.

this.ruteador.navigate(
    ["libros", "edicion"], 
    {queryParamsHandling: "preserve"}
)

this.ruteador.navigate(
    ["libros", "edicion"], 
    {
        queryParams: {nivel: "2"},
        queryParamsHandling: "merge"
    }
)

Las promesas

Es una operación asíncrona que representa a un valor que puede estar disponible ahora, a futuro o nunca. 

Las promesas se declaran como una instancia de la clase "Promise".

const promesa: Promise = new Promise((resolve, reject) => {
        // Si la promesa se cumple
        resolve()

        // Si la promesa se rechaza
        reject()
})

Si una promesa se cumple, se ejecuta el método "then".

Si una promesa se rechaza, se ejecuta el método "catch".

promesa.then((respuesta)=> console.log(respuesta))

promesa.catch((error) => console.log(error))
promesa
    .then((respuesta)=> console.log(respuesta))
    .catch((error) => console.log(error))

Se puede simplificar de la siguiente manera:

Las promesas pueden ejecutarse independientemente, pero si es necesario ejecutar un proceso cuando todas se han cumplido, se usa "Promise.all".

const promesa1 = new Promise(...)
const promesa2 = new Promise(...)

Promise
    .all([promesa1, promesa2])
    .then([respuestas] => console.log(respuestas))
    .catch(error => console.log(error))

Observables

Ejecuta un proceso asíncrono como las promesas, pero se pueden ejecutar varias veces y además se pueden cancelar.

Los observables pertenecen a la programación reactiva.

Para usar un "Observable"  hay que importarlo de la librería "rxjs".

...
import { Observable, Observer } from "rxjs"
...
export class LibroListado {
...
    cadena: Observable<string>

    ngOnInit(){
        this.cadena= Observable.create(
            (observador: Observer) => {
                // Para enviar data
                observador.next("texto")


                // Para avisar de un error
                observador.error("ocurrió un error")

                // Cuando las tareas se cumplieron
                observador.complete()
            }
        )
    }
...
}

Para recibir las tres opciones posibles: data, error, completo, se usa el método "subscribe".

...
import { Observable, Observer } from "rxjs"
...
export class LibroListado {
...
    ngOnInit() {
        ...

        this.cadena.subscribe(
            data => console.log(data),
            error => console.log(error),
            completo => console.log("completo")
        )
    }
...
}

8 Angular: Protegiendo rutas

By Sergio Hidalgo

8 Angular: Protegiendo rutas

¿Cómo protegemos a las rutas? Protección de entrada: CanActivate, CanActivateChild. Protección de carga: CanLoad. Protección de salida: CanDeactivate.

  • 457