Do you suddenly find yourself with a requirement to know when your users switch routes in an Angular app?

And do you also need details about the route change?

If so, then you've come to the right place. I'll show you how to monitor route changes here.

I'll also explain why you might need to know when users switch routes.

Why? Why?? Why???

Why would you ever need to know when a user switches routes? There are a variety of reasons.

One of the most popular applications of this solution is with breadcrumbs

Let's say you want to put some pretty breadcrumbs at the top of the screen so the user can easily navigate back to one of the pages he or she visited before. 

And to make sure those breadcrumbs update properly, you need to know when the user changes routes.

But that's just one reason for monitoring route changes. There are others as well. I'm sure you'll come across some of them as you develop Angular apps.

Router: Not Just Something Cisco Makes

When it comes time to determine if a user switched routes, you'll use a service called Router. Like most services you use in Angular apps, you'll need to inject it into whichever class you're using to track route changes.

I inject it into my breadcrumb component like so:

constructor(private router: Router) { }

I include other dependencies in there as well. I'm just focusing on the Router service here for the sake of brevity.

But injecting the Router service doesn't do anything except make it available for use. You'll have to actually use it if you want to track route changes.

Using the Router Service

Here's how I use it to detect route changes:

  private listenForRouteChange() {
      filter(event => event instanceof NavigationEnd),
      (route: ActivatedRoute) => console.log("ROUTE IS " + route)

Again, I'm changing the code slightly for the purposes of this guide and to keep things simple.

That listenForRouteChange() method, by the way, gets called from ngOnInit(). That way it starts up immediately once the component is loaded.

Usually, that's what you'll want to do. It's not often the case that you wait for the user to take some specific action before you even begin listening for route changes.

Anyhoo, the Router service comes equipped with an Observable called events. If you want to listen for anything related to route changes, you'll need to subscribe to that Observable.

But that Observable will give you a lot of info. So you might want to get particular about which types of events you want to listen for.

Getting Picky With pipe()

As I stated above, when you listen for all route changes, you're going into information overload. You'll see events like navigation start, navigation end, navigation error, and navigation cancel.

Interestingly enough, all of those events are represented by inutitive class names: NavigationStart, NavigationEnd, NavigationError, and NavigationCancel.

So a big shout-out to Angular developers for making my day.

However, you probably don't need to listen for all that. The event you're looking for is NavigationEnd.

That's the event that gets fired when the user completes the route change. So it lives up to its name.

And since that's what you want to listen for, you need to pipe() the Observable and ignore everything else.

Now you know why that pipe() exists in the code block above. The first part of the pipe uses filter() to capture only NavigationEnd events.

The second line in the pipe, distinctUntilChanged(), is just a fancy way of saying: "Pretend nothing got emitted to the stream unless it's something different from the previous emission."

It's a nice way to avoid dupes.

Finally, the code above subscribes to the Observable and outputs the new route to the console.

You will, of course, want to do something other than simply outputting the new route. You'll do that something else within the subscribe() method.

Wrapping It Up

Now you know how to track route changes.

And you also know why it's sometimes a great idea to track route changes.

Feel free to take what you've learned here and put it in your own Angular apps.

Have fun!

Photo by cottonbro from Pexels