Back to Blog Posts

Navigating Angular Router Events: The Sweet Sixteen

https://miro.medium.com/v2/resize:fit:720/format:webp/1*7rmCAnxnTr7ShGOsCvZ8BQ.png

Photo by Alexander Andrews on Unsplash

Angular’s powerful built-in router is one of the best features of the framework. It enables developers to build applications with multiple views and navigate between them with ease. Whether you are debugging an issue around the router or if you want to implement some custom logic between navigations, the router provides a specific property, the Router.events property, that can be very handy for many given use cases.

Router Events

The Angular Router provides a series of events (16 in total) that allow you to track the lifecycle of the router. During each navigation, the Router emits navigation events through the Router.events property as observables. The events occur in the following sequence

How can I access them for debugging?

If you are debugging an issue around the router and want to see all navigation events printed on the console, Angular provides a way to do so. All we have to do is pass a flag in our app routing module, specifically in the RouterModule’s forRoot() method as it is explained as follows.

The RouterModule’s forRoot() method takes an optional second parameter, the ExtraOptions. The ExtraOptions is a set of configuration options for the router module. One of this options is the enableTracing option, which is a boolean flag that when enabled, logs all navigation events on the console for you, just by adding that simple flag.

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 {}

Router Events as Observables

If we are not debugging, but want to add an animation, small feature or run some logic between events, we need to access the Router’s events. In order to do so all we need to do is inject the router in the constructor of our component. Having done so, we can subscribe to the stream and listen to the events that happen on each navigation.

import { Event, Router } from "@angular/router";

export class AppComponent {
  constructor(public router: Router) {}

  ngOnInit() {
    this.router.events.subscribe((event: Event) => {
      console.log(event);
    });
  }
}

Most of the time, we would want to listen to a specific event of interest. For example, if we wanted to run some logic when the navigation started, we would want to only listen to the NavigationStart event. You can use the filter() operator from RxJS to look for that specific event, and subscribe to it in order to run the desired logic. For example we could do so like this:

export class AppComponent {
  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("Navigation has started", event);
    });
  }
}

Example from Angular Documentation

By filtering the event by the event’s instance, we can set our observables to listen to specific events and run any desired logic with them.

Now you know the Sweet Sixteen Router Events that the Angular Router provides, how to easily set a flag to print them out on the console for debugging purposes and how to access them to run custom logic. I hope they help you get to the bottom of that routing bug you have or better yet, implement great features around user navigation. See you on the next blog post!

Support

If you enjoyed this post and found it useful, consider buying me a coffee. Thanks in advance!

Buy Me a Coffee at ko-fi.comBack to Blog Posts
Using Angular v.17.3.3 🚀