Una guía completa para el enrutamiento en Angular
Publicado: 2022-03-10En caso de que aún no esté muy familiarizado con Angular 7, me gustaría acercarlo a todo lo que este impresionante marco de interfaz de usuario tiene para ofrecer. Lo guiaré a través de una aplicación de demostración de Angular que muestra diferentes conceptos relacionados con el enrutador, como:
- La salida del enrutador,
- Rutas y caminos,
- Navegación.
También le mostraré cómo usar Angular CLI v7 para generar un proyecto de demostración donde usaremos el enrutador Angular para implementar el enrutamiento y la navegación. Pero primero, permítame presentarle Angular y repasar algunas de las nuevas características importantes en su última versión.
Presentamos Angular 7
Angular es uno de los marcos front-end más populares para crear aplicaciones web del lado del cliente para la web móvil y de escritorio. Sigue una arquitectura basada en componentes donde cada componente es una pieza de código aislada y reutilizable que controla una parte de la interfaz de usuario de la aplicación.
Un componente en Angular es una clase TypeScript decorada con el decorador @Component
. Tiene una plantilla adjunta y hojas de estilo CSS que forman la vista del componente.
Angular 7, la última versión de Angular, se lanzó recientemente con nuevas características, particularmente en herramientas y rendimiento de CLI, como:
- Indicaciones de CLI: un comando común como
ng add
yng new
ahora puede solicitar al usuario que elija las funcionalidades para agregar a un proyecto, como enrutamiento y formato de hojas de estilo, etc. - Agregar desplazamiento a Angular Material CDK (Component DevKit).
- Agregar soporte de arrastrar y soltar a Angular Material CDK.
- Los proyectos también están predeterminados para usar paquetes de presupuesto que advertirán a los desarrolladores cuando sus aplicaciones superen los límites de tamaño. De forma predeterminada, se lanzan advertencias cuando el tamaño tiene más de 2 MB y errores en 5 MB. También puede cambiar estos límites en su archivo
angular.json
. etc
Presentamos el enrutador angular
Angular Router es un poderoso enrutador de JavaScript creado y mantenido por el equipo central de Angular que se puede instalar desde el paquete @angular/router
. Proporciona una biblioteca de enrutamiento completa con la posibilidad de tener múltiples salidas de enrutador, diferentes estrategias de coincidencia de ruta, fácil acceso a los parámetros de ruta y protectores de ruta para proteger los componentes del acceso no autorizado.
El enrutador Angular es una parte central de la plataforma Angular. Permite a los desarrolladores crear aplicaciones de una sola página con múltiples vistas y permitir la navegación entre estas vistas.
Veamos ahora los conceptos esenciales del enrutador con más detalles.
La salida del enrutador
El Router-Outlet
es una directiva que está disponible en la biblioteca del enrutador donde el enrutador inserta el componente que se empareja en función de la URL del navegador actual. Puede agregar varios puntos de venta en su aplicación Angular, lo que le permite implementar escenarios de enrutamiento avanzados.
<router-outlet></router-outlet>
Cualquier componente que coincida con el enrutador lo representará como un hermano de la salida del enrutador.
Rutas y Senderos
Las rutas son definiciones (objetos) compuestas por al menos una ruta y un componente (o una ruta de redirección a) atributos. La ruta se refiere a la parte de la URL que determina una vista única que debe mostrarse, y el componente se refiere al componente Angular que debe asociarse con una ruta. Según una definición de ruta que proporcionamos (a través de un método estático RouterModule.forRoot(routes)
), el enrutador puede llevar al usuario a una vista específica.
Cada Route
asigna una path
URL a un componente.
La ruta puede estar vacía, lo que indica la ruta predeterminada de una aplicación y, por lo general, es el inicio de la aplicación.
La ruta puede tomar una cadena comodín ( **
). El enrutador seleccionará esta ruta si la URL solicitada no coincide con ninguna ruta para las rutas definidas. Esto se puede usar para mostrar una vista "No encontrado" o redirigir a una vista específica si no se encuentra ninguna coincidencia.
Este es un ejemplo de ruta:
{ path: 'contacts', component: ContactListComponent}
Si esta definición de ruta se proporciona a la configuración del enrutador, el enrutador representará ContactListComponent
cuando la URL del navegador para la aplicación web se convierta en /contacts
.
Estrategias de correspondencia de rutas
El enrutador angular proporciona diferentes estrategias de coincidencia de rutas. La estrategia predeterminada es simplemente verificar si la URL del navegador actual tiene el prefijo path .
Por ejemplo nuestra ruta anterior:
{ path: 'contacts', component: ContactListComponent}
También podría escribirse como:
{ path: 'contacts',pathMatch: 'prefix', component: ContactListComponent}
El atributo patchMath
especifica la estrategia de coincidencia. En este caso, su prefijo es el predeterminado.
La segunda estrategia de emparejamiento está llena . Cuando se especifica para una ruta, el enrutador verificará si la ruta es exactamente igual a la ruta de la URL del navegador actual:
{ path: 'contacts',pathMatch: 'full', component: ContactListComponent}
Parámetros de ruta
La creación de rutas con parámetros es una función común en las aplicaciones web. Angular Router le permite acceder a los parámetros de diferentes maneras:
- Utilizando el servicio ActivatedRoute,
- Usando el ParamMap observable disponible a partir de v4.
Puede crear un parámetro de ruta utilizando la sintaxis de dos puntos . Esta es una ruta de ejemplo con un parámetro de identificación :
{ path: 'contacts/:id', component: ContactDetailComponent}
Guardias de ruta
Un protector de ruta es una función de Angular Router que permite a los desarrolladores ejecutar cierta lógica cuando se solicita una ruta y, en función de esa lógica, permite o deniega el acceso del usuario a la ruta. Se usa comúnmente para verificar si un usuario ha iniciado sesión y tiene la autorización antes de poder acceder a una página.
Puede agregar un protector de ruta implementando la interfaz CanActivate
disponible en el paquete @angular/router
y extiende el método canActivate()
que contiene la lógica para permitir o denegar el acceso a la ruta. Por ejemplo, el siguiente guardia siempre permitirá el acceso a una ruta:
class MyGuard implements CanActivate { canActivate() { return true; } }
Luego puede proteger una ruta con el guardia usando el atributo canActivate
:
{ path: 'contacts/:id, canActivate:[MyGuard], component: ContactDetailComponent}
Directiva de Navegación
El enrutador angular proporciona la directiva routerLink
para crear enlaces de navegación. Esta directiva toma la ruta asociada con el componente al que navegar. Por ejemplo:
<a [routerLink]="'/contacts'">Contacts</a>
Salidas Múltiples Y Rutas Auxiliares
Angular Router admite múltiples puntos de venta en la misma aplicación.
Un componente tiene una ruta principal asociada y puede tener rutas auxiliares. Las rutas auxiliares permiten a los desarrolladores navegar por varias rutas al mismo tiempo.
Para crear una ruta auxiliar, necesitará una salida de enrutador con nombre donde se mostrará el componente asociado con la ruta auxiliar.
<router-outlet></router-outlet> <router-outlet name="outlet1"></router-outlet>
- La salida sin nombre es la salida principal.
- Todos los puntos de venta deben tener un nombre excepto el punto de venta principal.
A continuación, puede especificar la salida en la que desea representar su componente utilizando el atributo de salida:
{ path: "contacts", component: ContactListComponent, outlet: "outlet1" }
Creación de un proyecto de demostración de Angular 7
En esta sección, veremos un ejemplo práctico de cómo configurar y trabajar con Angular Router. Puede ver la demostración en vivo que crearemos y el repositorio de GitHub para el proyecto.
Instalación de Angular CLI v7
Angular CLI requiere Node 8.9+ , con NPM 5.5.1+ . Debe asegurarse de tener estos requisitos instalados en su sistema y luego ejecutar el siguiente comando para instalar la última versión de Angular CLI:
$ npm install -g @angular/cli
Esto instalará Angular CLI globalmente.
Nota : Es posible que desee utilizar sudo
para instalar paquetes globalmente, según su configuración de npm.
Creando un Proyecto Angular 7
Crear un nuevo proyecto está a un comando de distancia, simplemente necesita ejecutar el siguiente comando:
$ ng new angular7-router-demo
La CLI le preguntará si desea agregar enrutamiento (escriba N
para No porque veremos cómo podemos agregar enrutamiento manualmente) y qué formato de hoja de estilo le gustaría usar, elija CSS, la primera opción y luego presione Enter
. La CLI creará una estructura de carpetas con los archivos necesarios e instalará las dependencias requeridas del proyecto.
Creación de un servicio de back-end falso
Dado que no tenemos un back-end real con el que interactuar, crearemos un back-end falso utilizando la biblioteca angular-in-memory-web-api
, que es una API web en memoria para demostraciones y pruebas de Angular que emula operaciones CRUD sobre una API REST.
Funciona al interceptar las solicitudes HttpClient
enviadas al servidor remoto y las redirige a un almacén de datos local en memoria que debemos crear.
Para crear un back-end falso, debemos seguir los siguientes pasos:
- Primero, instalamos el módulo
angular-in-memory-web-api
, - A continuación, creamos un servicio que devuelve datos falsos,
- Finalmente, configure la aplicación para usar el back-end falso.
En su terminal, ejecute el siguiente comando para instalar el módulo angular-in-memory-web-api
de npm:
$ npm install --save angular-in-memory-web-api
Luego, genere un servicio de back-end usando:
$ ng gs backend
Abra el archivo src/app/backend.service.ts
e importe InMemoryDbService
desde el módulo angular-in-memory-web-api
:
import {InMemoryDbService} from 'angular-in-memory-web-api'
La clase de servicio necesita implementar InMemoryDbService
y luego anular el método createDb()
:
@Injectable({ providedIn: 'root' }) export class BackendService implements InMemoryDbService{ constructor() { } createDb(){ let contacts = [ { id: 1, name: 'Contact 1', email: '[email protected]' }, { id: 2, name: 'Contact 2', email: '[email protected]' }, { id: 3, name: 'Contact 3', email: '[email protected]' }, { id: 4, name: 'Contact 4', email: '[email protected]' } ]; return {contacts}; } }
Simplemente creamos una matriz de contactos y los devolvemos. Cada contacto debe tener una identificación.
Finalmente, simplemente necesitamos importar InMemoryWebApiModule
en el archivo app.module.ts
y proporcionar nuestro servicio de back-end falso.
import { InMemoryWebApiModule } from “angular-in-memory-web-api”; import { BackendService } from “./backend.service”; /* ... */ @NgModule({ declarations: [ /*...*/ ], imports: [ /*...*/ InMemoryWebApiModule.forRoot(BackendService) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
A continuación, cree un ContactService
que encapsule el código para trabajar con contactos:
$ ng gs contact
Abra el archivo src/app/contact.service.ts
y actualícelo para que se parezca al siguiente código:
import { Injectable } from '@angular/core'; import { HttpClient } from “@angular/common/http”; @Injectable({ providedIn: 'root' }) export class ContactService { API_URL: string = "/api/"; constructor(private http: HttpClient) { } getContacts(){ return this.http.get(this.API_URL + 'contacts') } getContact(contactId){ return this.http.get(`${this.API_URL + 'contacts'}/${contactId}`) } }
Agregamos dos métodos:
-
getContacts()
Para obtener todos los contactos. -
getContact()
Para obtener un contacto por id.
Puede establecer API_URL
en cualquier URL, ya que no vamos a utilizar un back-end real. Todas las solicitudes serán interceptadas y enviadas al back-end en memoria.
Creando nuestros componentes angulares
Antes de que podamos ver cómo usar las diferentes funciones del enrutador, primero creemos un montón de componentes en nuestro proyecto.
Dirígete a tu terminal y ejecuta los siguientes comandos:
$ ng gc contact-list $ ng gc contact-detail
Esto generará dos componentes ContactListComponent
y ContactDetailComponent
y los agregará al módulo principal de la aplicación.
Configuración de enrutamiento
En la mayoría de los casos, usará la CLI de Angular para crear proyectos con configuración de enrutamiento, pero en este caso, la agregaremos manualmente para que podamos tener una mejor idea de cómo funciona el enrutamiento en Angular.
Adición del módulo de enrutamiento
Necesitamos agregar AppRoutingModule
, que contendrá nuestras rutas de aplicación y una salida de enrutador donde Angular insertará el componente actualmente coincidente según la URL actual del navegador.
Ya veremos:
- Cómo crear un módulo angular para enrutamiento e importarlo;
- Cómo agregar rutas a diferentes componentes;
- Cómo agregar la salida del enrutador.
Primero, comencemos creando un módulo de enrutamiento en un app-routing.module.ts
. Dentro de src/app
crea el archivo usando:
$ cd angular7-router-demo/src/app $ touch app-routing.module.ts
Abra el archivo y agregue el siguiente código:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Comenzamos importando NgModule
del paquete @angular/core
, que es un decorador de TypeScript que se usa para crear un módulo Angular.
También importamos las clases RouterModule
y Routes
del paquete @angular/router
. RouterModule
proporciona métodos estáticos como RouterModule.forRoot()
para pasar un objeto de configuración al enrutador.
A continuación, definimos una matriz de routes
constantes de tipo Routes
que se utilizará para contener información para cada ruta.
Finalmente, creamos y exportamos un módulo llamado AppRoutingModule
(puedes llamarlo como quieras) que es simplemente una clase de TypeScript decorada con el decorador @NgModule
que toma algún objeto de metainformación. En el atributo de imports
de este objeto, llamamos al método estático RouterModule.forRoot(routes)
con la matriz de rutas como parámetro. En la matriz de exports
, agregamos RouterModule
.
Importación del módulo de enrutamiento
A continuación, debemos importar el enrutamiento de este módulo al módulo principal de la aplicación que se encuentra en el archivo src/app/app.module.ts
:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Importamos AppRoutingModule
desde ./app-routing.module
y lo agregamos en la matriz de imports
del módulo principal.
Adición de la salida del enrutador
Finalmente, necesitamos agregar la salida del enrutador. Abra el archivo src/app/app.component.html
que contiene la plantilla de la aplicación principal y agregue el componente <router-outlet>
:
<router-outlet></router-outlet>
Aquí es donde Angular Router representará el componente que corresponde a la ruta del navegador actual.
Esos son todos los pasos que debemos seguir para configurar manualmente el enrutamiento dentro de un proyecto Angular.
Creación de rutas
Ahora, agreguemos rutas a nuestros dos componentes. Abra el src/app/app-routing.module.ts
y agregue las siguientes rutas a la matriz de routes
:
const routes: Routes = [ {path: 'contacts' , component: ContactListComponent}, {path: 'contact/:id' , component: ContactDetailComponent} ];
Asegúrese de importar los dos componentes en el módulo de enrutamiento:
import { ContactListComponent } from './contact-list/contact-list.component'; import { ContactDetailComponent } from './contact-detail/contact-detail.component';
Ahora podemos acceder a los dos componentes desde las rutas /contacts
y contact/:id
.
Adición de enlaces de navegación
A continuación, agreguemos enlaces de navegación a nuestra plantilla de aplicación utilizando la directiva routerLink
. Abra src/app/app.component.html
y agregue el siguiente código en la parte superior de la salida del enrutador:
<h2><a [routerLink] = "'/contacts'">Contacts</a></h2>
A continuación, debemos mostrar la lista de contactos en ContactListComponent
. Abra src/app/contact-list.component.ts
luego agregue el siguiente código:
import { Component, OnInit } from '@angular/core'; import { ContactService } from '../contact.service'; @Component({ selector: 'app-contact-list', templateUrl: './contact-list.component.html', styleUrls: ['./contact-list.component.css'] }) export class ContactListComponent implements OnInit { contacts: any[] = []; constructor(private contactService: ContactService) { } ngOnInit() { this.contactService.getContacts().subscribe((data : any[])=>{ console.log(data); this.contacts = data; }) } }
Creamos una matriz de contacts
para contener los contactos. A continuación, inyectamos ContactService
y llamamos al método getContacts()
de la instancia (en el evento del ciclo de vida ngOnInit
) para obtener contactos y asignarlos a la matriz de contacts
.
A continuación, abra el archivo src/app/contact-list/contact-list.component.html
y agregue:
<table> <tr> <th>Name</th> <th>Email</th> <th>Actions</th> </tr> <tr *ngFor="let contact of contacts" > <td>{{ contact.name }}</td> <td>{{ contact.email }}</td> <td> <a [routerLink]="['/contact', contact.id]">Go to details</a> </td> </tr> </table>
Recorremos los contactos y mostramos el nombre y el correo electrónico de cada contacto. También creamos un enlace al componente de detalles de cada contacto usando la directiva routerLink
.
Esta es una captura de pantalla del componente:
Cuando hacemos clic en el enlace Ir a detalles , nos llevará a ContactDetailsComponent
. La ruta tiene un parámetro id
, veamos como podemos acceder a ella desde nuestro componente.
Abra el archivo src/app/contact-detail/contact-detail.component.ts
y cambie el código para que se parezca al código siguiente:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ContactService } from '../contact.service'; @Component({ selector: 'app-contact-detail', templateUrl: './contact-detail.component.html', styleUrls: ['./contact-detail.component.css'] }) export class ContactDetailComponent implements OnInit { contact: any; constructor(private contactService: ContactService, private route: ActivatedRoute) { } ngOnInit() { this.route.paramMap.subscribe(params => { console.log(params.get('id')) this.contactService.getContact(params.get('id')).subscribe(c =>{ console.log(c); this.contact = c; }) }); } }
Inyectamos ContactService
y ActivatedRoute
en el componente. En el evento de ciclo de vida ngOnInit()
, recuperamos el parámetro de identificación que se pasará de la ruta y lo usamos para obtener los detalles del contacto que asignamos a un objeto de contact
.
Abra el archivo src/app/contact-detail/contact-detail.component.html
y agregue:
<h1> Contact # {{contact.id}}</h1> <p> Name: {{contact.name}} </p> <p> Email: {{contact.email}} </p>
Cuando visitamos nuestra aplicación por primera vez desde 127.0.0.1:4200/
, la salida no representa ningún componente, así que redirijamos la ruta vacía a la ruta de contacts
agregando la siguiente ruta a la matriz de rutas:
{path: '', pathMatch: 'full', redirectTo: 'contacts'}
Queremos hacer coincidir la ruta vacía exacta, por eso especificamos la estrategia de coincidencia completa .
Conclusión
En este tutorial, hemos visto cómo usar Angular Router para agregar enrutamiento y navegación a nuestra aplicación. Hemos visto diferentes conceptos como la salida del enrutador, rutas y caminos y creamos una demostración para mostrar prácticamente los diferentes conceptos. Puede acceder al código desde este repositorio.