When routing in any application there comes a point where it makes sense architecturally to share data during navigation. Angular has several tools for sharing data across your apps routing system including Route Guards, Route Resolvers, the Route API and the ActivatedRoute API.

The ActivatedRoute API is an interesting function within Angular as it specifically has to do with the currently activated route in your app and holds a conglomerate of information pertaining to the router.

Let’s dive into the defining the ActivatedRoute, retrieving it, discovering what data is available and what you can do with it.

the activated route is similar to a path of switches on a motherboard

What is an activated route?

The Angular Docs define the ActivatedRoute as

A service that is provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query params and the global fragment.

Screenshot

With this data we can handle route specific logic, use route specific state and retrieve the route fragments of the current URL.

In a component, we can access this data by injecting the ActivatedRoute API inside the constructor:

import { ActivatedRoute } from '@angular/router'
...
constructor(private activatedRoute: ActivatedRoute) {}

What route data is available?

Here is a section from the docs outlining the properties available in the ActivatedRoute API:

snapshot: ActivatedRouteSnapshot
The current snapshot of this route

url: Observable<UrlSegment[]>
An observable of the URL segments matched by this route.

params: Observable<Params>
An observable of the matrix parameters scoped to this route.

queryParams: Observable<Params>
An observable of the query parameters shared by all the routes.

fragment: Observable<string>
An observable of the URL fragment shared by all the routes.

data: Observable<Data>
An observable of the static and resolved data of this route.

outlet: string
The outlet name of the route, a constant.

component: Type<any> | string | null
The component of the route, a constant.

routeConfig: Route | null Read-Only
The configuration used to match this route.

root: ActivatedRoute Read-Only
The root of the router state.

parent: ActivatedRoute | null Read-Only
The parent of this route in the router state tree.

firstChild: ActivatedRoute | null Read-Only
The first child of this route in the router state tree.

children: ActivatedRoute[] Read-Only
The children of this route in the router state tree.

pathFromRoot: ActivatedRoute[] Read-Only
The path from the root of the router state tree to this route.

paramMap: Observable<ParamMap> Read-Only
An Observable that contains a map of the required and optional parameters specific to the route. The map supports retrieving single and multiple values from the same parameter.

queryParamMap: Observable<ParamMap> Read-Only
An Observable that contains a map of the query parameters available to all routes. The map supports retrieving single and multiple values from the query parameter.

The snapshot property from the ActivatedRoute contains this ActivatedRouteSnapshot object:

interface ActivatedRouteSnapshot {
    routeConfig: Route | null
    url: UrlSegment[]
    params: Params
    queryParams: Params
    fragment: string
    data: Data
    outlet: string
    component: Type<any> | string | null
    root: ActivatedRouteSnapshot
    parent: ActivatedRouteSnapshot | null
    firstChild: ActivatedRouteSnapshot | null
    children: ActivatedRouteSnapshot[]
    pathFromRoot: ActivatedRouteSnapshot[]
    paramMap: ParamMap
    queryParamMap: ParamMap
    toString(): string
}

Some properties are duplicated: because they hold the same kind of data but they are not the same types of data. The snapshot properties hold synchronous information that you can access right away; the ActivatedRoute properties that have the same key names hold observable data which is asynchronous.

Summary of data found in ActivatedRoute

Route Tree and Components

The component, root, parent,firstChild, children and pathFromRoot keys comprise the Route Tree which is made up of ActivatedRouteSnapshots that are being loaded in the route, including the components that are part of the route.

Route State

The Route state lies in the data property, which is where Resolver and Observable data are kept. Data put into a Route from the resolver or routeGuard is available here.

URL Information

The url, params, queryParams, fragment, paramMap and queryParamMap keys make up the URL information. The url property only holds the last segment of the URL. For example if your URL path was /home/pangolins the last segment would be pangolins. If you want to access the current URL path you would want to get that from the Router API.

Other Route Metadata

More Metadata is stored in the routeConfig and outlet properties. The routeConfig holds a Route object and the outlet key stores the name of the router outlet being used.

What is the difference between the ActivatedRoute and ActivatedRouteSnapshot?

The ActivatedRoute is the API that holds observable data that you can use to react to events with. You can subscribe to specific observable properties to get data from it asynchronously. The ActivatedRoute also contains ActivatedRouteSnapshot. The ActivatedRouteSnapshot holds the same activated route data but is a static property.

Static activated route snapshot data

constructor(private activatedRoute: ActivatedRoute) {
    const activatedRouteSnapshot = activatedRoute.snapshot;
}

Observable activated route data

For observable data you must subscribe to a specific observable property on the ActivatedRoute object, for example the data property:

constructor(private activatedRoute: ActivatedRoute) {
    activatedRoute.data.subscribe((data) => ...)
}

What can you do with this knowledge?

Get URL Params

You can get the URL params using the activatedRoutes query param map, along with its built in get method for retrieving the parameters value. (tip: it is possible for parameters to have casing issues; it’s recommended that you normalize keys before getting the value).

// www.briebug.com?favoritepangolin=leroyjenkins
ngOnInit() {
    const params = this._activatedRoute.snapshot.queryParamMap;
    const favoritePangolin = params.get('favoritepangolin');
}

Get URL Fragment

You may want to get the current URL fragment while the user travels along your page in order to give them a fragment specific user experience. To do that, you can just subscribe to the ActivatedRoute changes.

listenForRouteFragment(){
    this.activatedRoute$.fragment.subscribe((fragment: string) => {
        if (fragment === 'youGotPaid') {
            this.makeItRain();
        };
    });
}

Pass data and retrieve resolver data

Data can be passed during navigation and retrieved in the component within the activated route. You can include data in the route configuration:

const routes: RouterConfig = [
    {
        path: 'pangolins',
        component: cutePangolinComponent,
        data: {
            pangolinArray: [ ... ]
        }
    ];

However this approach is not as useful, or as common, as others. You can access this data within the data property of ActivatedRoute but the data is static. A dynamic approach would be much more useful, which is where having a resolver comes into play. With a resolver I can fetch my array of Pangolins from the server. (tip: when data is necessary for rendering a view it can be useful to also use a route guard to make sure the data is available before loading the view).

const routes: RouterConfig = [
    {
        path: 'pangolins',
        component: cutePangolinComponent,
        resolve: {
            pangolins: PangolinResolver
        }
    ];

Notice how the resolver is inside the resolve property and not the data property. When our data resolves, Angular will take care of putting the data requested inside the data property on the ActivatedRoute. We can then get our data synchronously or asynchronously inside our component.

constructor(private activatedRoute: ActivatedRoute) {
    this.pangolins = activatedRoute.snapshot.data['pangolins']
}

Asynchronously may be a good option if there is some logic you want to perform on the data.

listenForPangolins() {
    this.activatedRoute.data['pangolins'].subscribe((pangolins) => {
        this.getImagesOfPangolins(pangolins)
    })
}

Debugging the Router

Logging the router state can be a helpful tool for debugging routes in Angular. The ActivatedRoute holds all the router state you need to see your current route path and history. This can be useful in creating a more textual or visual representation of what your router state is; especially if your app holds a complex spaghetti of routes.

constructor(private activatedRoute: ActivatedRoute) {

    // what child routes are being loaded right now?
    const childRouteSnapshots = activatedRoute.snapshot.children;
    console.log('children snapshots: ', childRouteSnapshots);

    // what is the parent of this route?
    const parentRouteSnapshot = activatedRoute.snapshot.parent;
    console.log('parent route snapshot: ', parentRouteSnapshot);

    // what is the full path of my router?
    const routePath = activatedRoute.snapshot.pathFromRoot;
    console.log('my path from root: ', routePath);

    // I have multiple router outlets. Is this using the correct router outlet?
    const outletName = activatedRoute.snapshot.outlet;
    console.log('current router outlet name: ', outletName);
}

What about using Router?

Great question! The Angular Router API comes with many methods used to control the router as well as some info about the current route. A good rule of thumb is to use the Router API if you need to manipulate the route (redirecting, navigating to another part of the app, etc) or need the current full textual URL path. If you just need information about the route and the router state then you should use the ActivatedRoute API.

I just came here to get the URL Parameters…

Well now you know so much more! The ActivatedRoute is such a large object that it can be cumbersome to work through. Now that you know the basics of what data is located in what properties you will have an easier time finding the information you need about your router. The Activated Route is a great API for getting data from your router, knowing your router’s state and becoming more familiar with how the Angular router functions at its core.