Ejemplo de cómo realizar el enrutado en una aplicación Angular

Una vez ya tienes los Componentes de Angular creados, el siguiente punto a programar en tu proyecto son las rutas que permita al usuario navegar y obtener la información que contienen los diferentes objetos. El proyecto https://github.com/al118345/Ejemplo_routing_angular contiene un ejemplo de angular web con todas los implementaciones analizadas en este artículo o el siguiente video explicativo:

1. Añade Angular routing al proyecto

Al crear tu proyecto, Angular pregunta

? Would you like to add Angular routing? (y/N)

Contesta y. Automáticamente, Angular ha creado un fichero llamado app-routing.module.ts con contenido similar a este (en mi caso ya he añadido algunas rutas a algunos componentes):


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from "./component/home/home.component";
import {VistaSecundariaComponent} from "./component/vista-secundaria/vista-secundaria.component";
import {VistaTerceariaComponent} from "./component/vista-tercearia/vista-tercearia.component";
import {UsersGuard} from "./guard/users.guard";

const routes: Routes = [
  { path: 'vista2', component: VistaTerceariaComponent,  canActivate: [UsersGuard] },
  { path: 'vista1/:id', component: VistaSecundariaComponent },
  { path: 'vista1', component: VistaSecundariaComponent },
  { path: 'home', component: HomeComponent },
  { path: '', component: HomeComponent },
  { path: '**',  component: HomeComponent }
];

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

Además, ha añadido una referencia al fichero en el documento app-module.ts. Exactamente lo encuentra en la linea 5 con el import y la linea 14 incluido en los imports.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

En el caso que no lo tengas, lo puedes crear manualmente y añadirlo a tu proyecto.

2. Explicación de cómo funciona

Básicamente es un fichero json donde las keys marcan las diferentes funcionalidades.

La primera funcionalidad es el path que contiene la cadena con la dirección que se debe introducir para invocar el componente. El siguiente campo es él component y básicamente identifica el objeto que necesitamos para la dirección indicada.

A continuación mostramos el siguiente ejemplo extraído del proyecto https://github.com/al118345/Ejemplo_routing_angular


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from "./component/home/home.component";
import {VistaSecundariaComponent} from "./component/vista-secundaria/vista-secundaria.component";
import {VistaTerceariaComponent} from "./component/vista-tercearia/vista-tercearia.component";
import {UsersGuard} from "./guard/users.guard";

const routes: Routes = [
  { path: 'vista2', component: VistaTerceariaComponent,  canActivate: [UsersGuard] },
  { path: 'vista1/:id', component: VistaSecundariaComponent },
  { path: 'vista1', component: VistaSecundariaComponent },
  { path: 'home', component: HomeComponent },
  { path: '', component: HomeComponent },
  { path: '**',  component: HomeComponent }
];

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

Realmente tenemos un fichero pequeño con muchas funcionalidades que voy a detallar a continuación linea a linea Importante: el orden de la líneas es importante. El interprete empieza analizando la primera linea y se detiene en la primera opción que cumpla el criterio del path, es decir, vamos de arriba a abajo y paramos cuando cumplimos el criterio.
  • {path: 'home', component: HomeComponent} Considero que HomeComponent es la vista inicial del programa y, por lo tanto, será la primera en mostrarse al usuario. Cuando la ruta del proyecto sea /home abriremos HomeComponent
  • {path: '', component: HomeComponent} En caso de únicamente escribir el dominio mostraremos HomeComponent, la pantalla de inicio del proyecto. Esta linea la recomendamos situar en la penúltima posición.
  • {path: '**', component: HomeComponent} En caso de escribir cualquier dirección que no este contemplada en el fichero por las líneas anteriores, mostraremos HomeComponent Importante, esta linea debe estar la última del fichero. Es la última opción.
  • {path: 'vista1', component: VistaSecundariaComponent} En caso de escribir la dirección vista1 en la ruta del dominio automáticamente mostraremos VistaSecundariaComponent
  • {path: 'vista1/:id', component: VistaSecundariaComponent} En caso de escribir la dirección vista1/:id mostraremos VistaSecundariaComponent aunque con una diferencia notable.

    Cómo os habréis dado cuenta, se trata de una ruta compuesta por una parte fija y una parte definida cómo id. Esta parte id puede ser cualquier valor y, además, sera proporcionado como parámetro get al componente.

    A continuación, os mostraremos cómo podéis obtener este valor desde este objeto:

    import { Component, OnInit } from '@angular/core';
    import {ActivatedRoute} from '@angular/router';
    
    @Component({
      selector: 'app-vista-secundaria',
      templateUrl: './vista-secundaria.component.html',
      styleUrls: ['./vista-secundaria.component.css']
    })
    export class VistaSecundariaComponent implements OnInit {
      public  id:string | null;
    
      constructor( private route:ActivatedRoute ) {
        this.id = this.route.snapshot.paramMap.get('id');
        if (this.id == null){
          this.id = '0'
        }
      }
    
      ngOnInit(): void {
      }
    
    }

    Simplemente con ActivatedRoute nos permite obtener el parámetro id cómo si fuera un parámetro get de forma muy sencilla. Si quieres ver en acción este componente visita el proyecto https://github.com/al118345/Ejemplo_routing_angular.
  • {path: 'vista2', component: VistaTerceariaComponent, canActivate: [UsersGuard]} Este caso es el más complejo ya que usamos canActivate: [UsersGuard]. Esta funcionalidad sirve para activar un sistema de seguridad sobre la ruta, es decir, cada vez que tecleamos una ruta vista2 en el proyecto comprobará si se cumple una condición. La implementación viene marcada por la función UsersGuard que explicaremos en el siguiente punto del artículo.

2.Implementar UsersGuard

Hay proyectos que, para acceder a ciertas vistas, tienes que tener ciertos permisos. Para implementar este sistema de seguridad podemos utilizar guard a través del siguiente comando:

ng g guard guard/user

La parte guard/user corresponde al nombre y localización del objeto que vamos a crear, es decir, la puedes modificar. Una vez ejecutado os aparecerán 4 opciones, seleccionad la primera CanActivate

Al final, con este comando hemos creado el fichero users.guard.ts y lo hemos modificado obteniendo el siguiente resultado:

import { Injectable } from '@angular/core';
import {CanActivate, Router, } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class UsersGuard implements CanActivate {
  constructor(private router: Router) { }
  canActivate() {
    if (localStorage.getItem('currentUser') === 'test') {
      alert('Log correcto.')
      // logged in so return true
      return true;
    }
    alert('Error de login.')
    // not logged in so redirect to login page
    this.router.navigate(['/home']);
    return false;
  }
}

En este caso, simplemente comprobamos que se ha almacenado la palabra currentUser con valor test en las cookies de navegación del usuario en la web. En caso afirmativo, se devuelve true (puede navegar a la vista), en caso negativo, devolvemos false y se redirecciona a otra vista (por ejemplo la vista del login).

Post data: Para almacenar información en las cookies puedes utilizar localStorage de la siguiente forma localStorage.setItem('currentUser', 'test');