In this post you’ll learn how to get the current route, or URL, with the Angular router.
There’s two ways you can to do this, Observables or snapshots - and we’ll cover both approaches.
Getting the URL or current route is a common practice when dealing with routed components that access router state.
Despite having two approaches, we’ll be using the ActivatedRoute
injectable for both - which makes switching between both styles easy. We can either get Observables of various pieces of the router object, or access a static snapshot of the router state. Depending what you’re doing with a component, you’ll want to know when to choose each style.
Let’s assume the following component and inject the ActivatedRoute
provider:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
console.log(this.route); // ActivatedRoute
}
}
The ActivatedRoute is a class the router populates with data that looks like this:
class ActivatedRoute {
snapshot: ActivatedRouteSnapshot
title: Observable<string | undefined>
url: Observable<UrlSegment[]>
params: Observable<Params>
queryParams: Observable<Params>
fragment: Observable<string | null>
data: Observable<Data>
outlet: string
component: Type<any> | null
routeConfig: Route | null
root: ActivatedRoute
parent: ActivatedRoute | null
firstChild: ActivatedRoute | null
children: ActivatedRoute[]
pathFromRoot: ActivatedRoute[]
paramMap: Observable<ParamMap>
queryParamMap: Observable<ParamMap>
}
Lots of things to access! But before you do, let’s look further…
Notice that many of the property values are Observables, such as Observable<Params>
and Observable<ParamMap>
and many others.
But - you can also see url: Observable<UrlSegment[]>
which gives us an Observable of URL segments.
Now, if you need an Observable, or prefer the reactive style, then by all means subscribe to this Observable to get the information.
✨ The benefit of an Observable is: whenever the URL changes, and the same component remains in view, we’re notified each time.
Each time our Observable emits we get an Array of UrlSegment objects:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.url.subscribe(console.log); // UrlSegment[]
}
}
The UrlSegment
is available for developers to you too, but the router uses it internally. Here’s what it looks like:
class UrlSegment {
constructor(path: string, parameters: { [name: string]: string; })
path: string
parameters: {...}
parameterMap: ParamMap
}
So, that answers our question on how to get the current route from Angular’s router. At this point we can simply log out any properties we’re interested in:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.url.subscribe((event) => {
console.log(event[0]); // It's an array remember [0]
console.log(event[0].path); // e.g. /products
console.log(event[0].parameters); // e.g. { id: 'x8klP0' }
});
}
}
This syntax is nice, and allows us to get the current route and URL information, but we’re using [0]
(which I really don’t like)…
Here’s my take to make it super clean, using parameter destructuring and a named variable followed by some object destructuring:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.url.subscribe(([url]) => {
const { path, parameters } = url;
console.log(path); // e.g. /products
console.log(parameters); // e.g. { id: 'x8klP0' }
});
}
}
So, that’s the Observable side of things taken care of - what about a simpler way to get the current route or URL in Angular?
This is where we introduce snapshots, the ActivatedRouteSnapshot to be specific.
Thankfully, we can keep using ActivatedRoute
(the injectable) and access the .snapshot
property:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
console.log(this.route.snapshot); // ActivatedRouteSnapshot
}
}
Our ActivatedRouteSnapshot
contains a url
property that has path
and parameters
available:
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({...})
export class ProductComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
console.log(this.route.snapshot); // ActivatedRouteSnapshot
console.log(this.route.snapshot.url); // UrlSegment[]
console.log(this.route.snapshot.url[0]); // UrlSegment
console.log(this.route.snapshot.url[0].path); // e.g. /products
console.log(this.route.snapshot.url[0].parameters); // e.g. { id: 'x8klP0' }
}
}
And that’s it! You’re now fully equipped to tackle URLs and current routes with Angular’s router - but I’d also like to think that you learned how to dive into the classes that are assembled behind the scenes by the Angular router so you feel more confident diving into more properties and learning more of the smaller, hidden gems.
🏆 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!