Router Events

Listen to the Navigation Lifecycle

Router Events

The Router emits an event for every step of navigation — NavigationStart, NavigationEnd, NavigationError, and more.

4 min read Level 3/5 #angular#router#events
What you'll learn
  • Subscribe to router.events
  • Filter for NavigationEnd
  • Build a global loading indicator

Router.events is an Observable that fires for every phase of a navigation. You can use it for analytics, global loading bars, scroll restoration, or debugging “why did this navigation fail”.

The main event types

  • NavigationStart — navigation kicked off
  • RoutesRecognized — the URL parsed into a route tree
  • GuardsCheckStart / GuardsCheckEnd — guards ran
  • ResolveStart / ResolveEnd — resolvers ran
  • NavigationEnd — succeeded, URL is now active
  • NavigationCancel — guard returned false or redirected
  • NavigationError — something threw

Track page views

import { Component, inject } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({ selector: 'app-root', standalone: true, template: `<router-outlet />` })
export class AppComponent {
  private router = inject(Router);

  constructor() {
    this.router.events
      .pipe(
        filter(e => e instanceof NavigationEnd),
        takeUntilDestroyed(),
      )
      .subscribe((e: NavigationEnd) => {
        analytics.track('pageview', { url: e.urlAfterRedirects });
      });
  }
}

Global loading indicator

Toggle a signal while navigation is in flight.

import { signal } from '@angular/core';
import { NavigationCancel, NavigationEnd, NavigationError, NavigationStart } from '@angular/router';

loading = signal(false);

this.router.events.pipe(takeUntilDestroyed()).subscribe(e => {
  if (e instanceof NavigationStart) this.loading.set(true);
  if (e instanceof NavigationEnd || e instanceof NavigationCancel || e instanceof NavigationError) {
    this.loading.set(false);
  }
});

Render a top-bar spinner whenever loading() is true. It feels far snappier than per-route skeletons for short navigations.

Services & Dependency Injection →