In this post you’re going to learn how to detect route changes with the Angular Router.
This is a common practice when dealing with routed components, where you want to get notified of what is happening with the router (in its various phases).
For instance, there are start and end events with the router, as well as many phases and checks that get processed before navigating to each route.
An example of when to detect a route change in Angular could be showing a loading spinner or to pass some data to a logging service.
💎 Looking for query params instead of listening to all router events?
For this, we’ll create a simple App
component and inject the Router
into the constructor
:
import { Component } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router';
@Component({
selector: 'my-app',
standalone: true,
imports: [RouterOutlet],
template: `
<router-outlet></router-outlet>
`,
})
export class App {
constructor(private router: Router) {}
}
Now, if you’re a seasoned Angular developer you’ll have likely seen the RouterEvent before.
This RouterEvent
class serves as the base class for these router-related events (in alphabetical order):
GuardsCheckEnd
GuardsCheckStart
NavigationCancel
NavigationEnd
NavigationError
NavigationSkipped
NavigationStart
ResolveEnd
ResolveStart
RoutesRecognized
The above list of classes are potential outcomes that the router may emit. For example if a user starts to navigate to a new view, events NavigationStart
and NavigationEnd
will be called.
The get hold of this information (and much more) we can subscribe to the router.events
Observable and log out the event
:
import { Component, OnInit } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router';
@Component({
selector: 'my-app',
standalone: true,
imports: [RouterOutlet],
template: `
<router-outlet></router-outlet>
`,
})
export class App implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe((event) => console.log(event));
}
}
If we click and transition to a new view, we’ll see something like this being logged out in the console
:
NavigationStart {...}
RoutesRecognized {...}
GuardsCheckStart {...}
ChildActivationStart {...}
ActivationStart {...}
GuardsCheckEnd {...}
ResolveStart {...}
ResolveEnd {...}
ActivationEnd {...}
ChildActivationEnd {...}
NavigationEnd {...}
Lots happening! So what about listening to events that you care about, for example just NavigationStart
?
Well, you could filter them out conditionally with if
statements:
import { Component, OnInit } from '@angular/core';
import { Router, RouterOutlet, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
@Component({
selector: 'my-app',
standalone: true,
imports: [RouterOutlet],
template: `
<router-outlet></router-outlet>
`,
})
export class App implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
// Navigation is starting... show a loading spinner perhaps?
// blog on that here: ultimatecourses.com/blog/angular-loading-spinners-with-router-events
}
if (event instanceof NavigationEnd) {
// We've finished navigating
}
if (event instanceof NavigationError) {
// something went wrong, log the error
console.log(event.error);
}
});
}
}
If you want just one event, for example NavigationStart
we can introduce filter()
from RxJS and pipe the Observable, to only emit upon the specific event:
import { Component, OnInit } from '@angular/core';
import { Router, RouterOutlet, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
@Component({
selector: 'my-app',
standalone: true,
imports: [RouterOutlet],
template: `
<router-outlet></router-outlet>
`,
})
export class App implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events.pipe(
filter((event) => event instanceof NavigationStart)
).subscribe((event) => {
// this only fires for `NavigationStart` and no other events
});
}
}
And that’s it! There are many events you can hook into by subscribing to Angular’s router events to detect route changes - one thing I should also add is that this would typically done in a central place, such as a the root component.
If, of course, you need to subscribe and detect route changes elsewhere - you’re free to do so.
Here’s a live example that logs out the events from what we’ve covered so far so you can see it in action:
Angular’s router is a powerful mechanism, and detecting route changes is just one of the many features it offers.
🏆 Check out my brand new Angular v15 course where you’ll learn Angular, TypeScript, RxJS and state management principles from beginning to expert level.
Happy routing!