hace 2 años
El potente Router integrado de Angular es una de las mejores características del framework. Permite a los desarrolladores construir aplicaciones con múltiples vistas y navegar entre ellas con facilidad. Ya sea que estés depurando un problema relacionado con el router o implementando lógica personalizada entre navegaciones, el router proporciona una propiedad específica, la propiedad Router.events, que puede ser muy útil para muchos casos de uso.

- Eventos del Router: El Ciclo de Vida de la Navegación en Angular
- Depuración de Rutas: Imprimiendo Eventos en la Consola
- Eventos del Router como Observables: Lógica Personalizada entre Navegaciones
- Filtrando Eventos Específicos con RxJS
- Casos de Uso Prácticos de los Eventos del Router
- Tabla Comparativa de Eventos de Router
- Preguntas Frecuentes sobre Eventos del Router en Angular
- Conclusión
El Router de Angular proporciona una serie de eventos (16 en total) que te permiten rastrear el ciclo de vida del router. Durante cada navegación, el Router emite eventos de navegación a través de la propiedad Router.events como observables. Estos eventos ocurren en una secuencia bien definida, permitiéndote intervenir y reaccionar en diferentes momentos del proceso de navegación.

A continuación, se presenta la secuencia de eventos de navegación en Angular:
- NavigationStart: La navegación comienza. Este evento se emite justo al inicio del proceso de navegación, antes de que se resuelva cualquier ruta o guardia.
- RouteConfigLoadStart: Antes de que el router cargue de forma lazy (carga perezosa) la configuración de una ruta. Este evento es crucial para módulos cargados de forma diferida, indicando el inicio de la carga.
- RouteConfigLoadEnd: Después de que una ruta ha sido cargada de forma lazy. Señala la finalización de la carga del módulo diferido, listo para ser activado.
- RoutesRecognized: Cuando el router analiza la URL y las rutas son reconocidas. En este punto, el router ha determinado qué ruta coincide con la URL actual.
- GuardsCheckStart: Cuando el router comienza la fase de guardias de enrutamiento. Inicia la verificación de los Guards (CanActivate, CanDeactivate, etc.) para determinar si la ruta puede ser activada.
- ChildActivationStart: Cuando el router comienza a activar los hijos de una ruta. Si la ruta tiene rutas hijas, este evento indica el inicio de la activación de la primera ruta hija.
- ActivationStart: Cuando el router comienza a activar una ruta. Señala el inicio del proceso de activación del componente asociado a la ruta.
- GuardsCheckEnd: Cuando el router finaliza la fase de guardias de enrutamiento exitosamente. Todos los Guards han sido evaluados y permiten la navegación.
- ResolveStart: Cuando el router comienza la fase de resolución de la ruta. Inicia la ejecución de los Resolvers, encargados de precargar datos antes de activar la ruta.
- ResolveEnd: Cuando el router finaliza la fase de resolución de la ruta exitosamente. Los Resolvers han completado su tarea y los datos están disponibles.
- ChildActivationEnd: Cuando el router finaliza la activación de los hijos de una ruta. Indica la finalización de la activación de todas las rutas hijas.
- ActivationEnd: Cuando el router finaliza la activación de una ruta. Señala que el componente de la ruta ha sido completamente activado y renderizado.
- NavigationEnd: Cuando la navegación termina exitosamente. Este evento indica que la navegación se ha completado sin errores y la nueva ruta está activa.
- NavigationCancel: Cuando la navegación es cancelada. La navegación puede ser cancelada por un Guard o por una nueva navegación que interrumpe la actual.
- NavigationError: Cuando la navegación falla debido a un error inesperado. Indica que ha ocurrido un error durante el proceso de navegación, como la imposibilidad de cargar un módulo o un error en un Resolver.
- Scroll: Cuando el usuario se desplaza (scroll). Este evento se emite cuando el usuario realiza scroll en la página, permitiendo implementar funcionalidades relacionadas con el desplazamiento.
Depuración de Rutas: Imprimiendo Eventos en la Consola
Si estás depurando un problema relacionado con el router y quieres ver todos los eventos de navegación impresos en la consola, Angular proporciona una manera sencilla de hacerlo. Simplemente tienes que pasar un flag en tu módulo de enrutamiento principal (usualmente AppRoutingModule), específicamente en el método RouterModule.forRoot(), como se explica a continuación.
El método RouterModule.forRoot() acepta un segundo parámetro opcional, ExtraOptions. ExtraOptions es un conjunto de opciones de configuración para el módulo del router. Una de estas opciones es enableTracing, que es un flag booleano que, cuando se habilita, registra todos los eventos de navegación en la consola. Es una herramienta invaluable para entender el flujo de navegación de tu aplicación durante el desarrollo.

Para habilitar el tracing de eventos, modifica tu AppRoutingModule de la siguiente manera:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes, { enableTracing: true })], exports: [RouterModule], }) export class AppRoutingModule {} Una vez habilitado enableTracing: true, abre la consola de tu navegador y observa cómo se imprimen todos los eventos de navegación a medida que interactúas con tu aplicación. Esto te dará una visión detallada del ciclo de vida del router en acción.
Más allá de la depuración, la verdadera potencia de los eventos del router reside en su capacidad para permitirte ejecutar lógica personalizada en diferentes puntos del ciclo de navegación. Para acceder a los eventos del Router y utilizarlos en tu código, necesitas inyectar el servicio Router en el constructor de tu componente. Una vez inyectado, puedes suscribirte al stream de eventos y escuchar los eventos que ocurren en cada navegación.
Aquí te mostramos cómo inyectar el Router y suscribirte a su stream de eventos en un componente:
import { Event, Router } from '@angular/router'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', template: '...' // Tu plantilla HTML }) export class AppComponent implements OnInit { constructor(public router: Router) {} ngOnInit() { this.router.events.subscribe((event: Event) => { console.log(event); }); } } En este ejemplo, cada vez que ocurre un evento de navegación, se imprimirá en la consola el objeto del evento. Sin embargo, en la mayoría de los casos, querrás escuchar un evento específico de interés. Por ejemplo, si deseas mostrar una animación de carga cuando comienza la navegación (NavigationStart) y ocultarla cuando termina (NavigationEnd), necesitarás filtrar el stream de eventos para reaccionar solo a estos eventos particulares.

Filtrando Eventos Específicos con RxJS
Para filtrar eventos específicos, puedes utilizar el operador filter() de RxJS. Esto te permite crear observables que solo emiten los eventos que te interesan, simplificando la lógica y mejorando la legibilidad de tu código.
Veamos un ejemplo de cómo filtrar el evento NavigationStart para ejecutar una lógica específica al inicio de la navegación:
import { Event, Router, NavigationStart } from '@angular/router'; import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { filter } from 'rxjs/operators'; @Component({ selector: 'app-root', template: '...' // Tu plantilla HTML }) export class AppComponent implements OnInit { navigationStart: Observable<NavigationStart>; constructor(router: Router) { this.navigationStart = router.events.pipe( filter((event: Event) => event instanceof NavigationStart) ) as Observable<NavigationStart>; } ngOnInit() { this.navigationStart.subscribe((event: NavigationStart) => { console.log('Navegación ha comenzado', event); // Aquí puedes colocar tu lógica, como mostrar un spinner de carga }); } } En este código, hemos creado un observable llamado navigationStart que solo emite eventos del tipo NavigationStart. Al suscribirnos a este observable, podemos ejecutar cualquier lógica deseada, como mostrar un indicador de carga o realizar un seguimiento de la navegación del usuario.
Casos de Uso Prácticos de los Eventos del Router
Los eventos del Router abren un abanico de posibilidades para mejorar la experiencia de usuario y añadir funcionalidades avanzadas a tus aplicaciones Angular. Algunos casos de uso comunes incluyen:
- Indicadores de Carga: Mostrar un spinner o barra de progreso durante la navegación para indicar al usuario que la aplicación está trabajando. Esto mejora la percepción de rendimiento y reduce la frustración. Puedes utilizar NavigationStart para mostrar el indicador y NavigationEnd, NavigationCancel o NavigationError para ocultarlo.
- Analíticas de Navegación: Registrar eventos de navegación para realizar un seguimiento de las rutas más visitadas, el tiempo de permanencia en cada página y el flujo de usuarios. Puedes utilizar eventos como NavigationEnd para enviar información a herramientas de analíticas.
- Gestión de Sesión y Autorización: Implementar lógica de autorización basada en eventos de navegación. Por ejemplo, puedes redirigir a los usuarios no autenticados a la página de inicio de sesión al detectar un evento NavigationStart hacia una ruta protegida.
- Animaciones de Transición: Crear animaciones suaves entre rutas para mejorar la experiencia visual de la navegación. Puedes utilizar eventos como ActivationStart y ActivationEnd para disparar animaciones de entrada y salida de componentes.
- Confirmación de Navegación: Implementar confirmaciones antes de abandonar una ruta con cambios no guardados. Puedes usar el evento NavigationStart junto con Guards (CanDeactivate) para preguntar al usuario si desea abandonar la página y perder los cambios.
Tabla Comparativa de Eventos de Router
| Evento | Descripción | Momento de Emisión |
|---|---|---|
| NavigationStart | Inicio de la navegación | Al comienzo del proceso de navegación |
| RouteConfigLoadStart | Inicio de carga de configuración de ruta (lazy) | Antes de cargar un módulo lazy |
| RouteConfigLoadEnd | Fin de carga de configuración de ruta (lazy) | Después de cargar un módulo lazy |
| RoutesRecognized | Rutas reconocidas | Después de analizar la URL y encontrar coincidencias de ruta |
| GuardsCheckStart | Inicio de verificación de Guards | Al comenzar la fase de Guards |
| ChildActivationStart | Inicio de activación de rutas hijas | Al comenzar la activación de rutas hijas |
| ActivationStart | Inicio de activación de ruta | Al comenzar la activación de una ruta |
| GuardsCheckEnd | Fin de verificación de Guards | Al finalizar exitosamente la fase de Guards |
| ResolveStart | Inicio de resolución de ruta | Al comenzar la fase de Resolvers |
| ResolveEnd | Fin de resolución de ruta | Al finalizar exitosamente la fase de Resolvers |
| ChildActivationEnd | Fin de activación de rutas hijas | Al finalizar la activación de rutas hijas |
| ActivationEnd | Fin de activación de ruta | Al finalizar la activación de una ruta |
| NavigationEnd | Fin de navegación exitosa | Al finalizar la navegación sin errores |
| NavigationCancel | Navegación cancelada | Cuando la navegación es cancelada |
| NavigationError | Error de navegación | Cuando ocurre un error durante la navegación |
| Scroll | Desplazamiento (Scroll) | Cuando el usuario se desplaza en la página |
Preguntas Frecuentes sobre Eventos del Router en Angular
- ¿Cuántos eventos del Router existen en Angular?
- Angular proporciona 16 eventos del Router que cubren todo el ciclo de vida de la navegación.
- ¿Cómo puedo ver los eventos del Router en la consola?
- Habilita la opción enableTracing: true en RouterModule.forRoot() en tu AppRoutingModule.
- ¿Cómo puedo ejecutar código cuando comienza la navegación?
- Suscríbete al evento NavigationStart del Router.events y filtra por la instancia de NavigationStart.
- ¿Puedo utilizar los eventos del Router para mostrar un indicador de carga?
- Sí, utiliza NavigationStart para mostrar el indicador y NavigationEnd, NavigationCancel o NavigationError para ocultarlo.
- ¿Qué operador de RxJS es útil para filtrar eventos específicos del Router?
- El operador filter() de RxJS es ideal para seleccionar eventos específicos basados en su tipo.
- ¿Los eventos del Router son observables?
- Sí, la propiedad Router.events es un observable que emite eventos de navegación.
Conclusión
Ahora conoces los 16 eventos del Router que Angular proporciona, cómo habilitar fácilmente un flag para imprimirlos en la consola con fines de depuración y cómo acceder a ellos para ejecutar lógica personalizada. Esperamos que esta guía te ayude a resolver ese error de enrutamiento que tienes pendiente o, mejor aún, a implementar excelentes funcionalidades alrededor de la navegación del usuario. Dominar los eventos del Router te permitirá crear aplicaciones Angular más dinámicas, interactivas y con una mejor experiencia de usuario. ¡Explora las posibilidades y lleva tus aplicaciones al siguiente nivel!
