DEV Community

Cover image for Accessing route params in Angular
thomas for This is Angular

Posted on • Edited on • Originally published at Medium

Accessing route params in Angular

There are various scenarios in which you may need to read parameters from your route. These parameters can be query parameters (e.g.: test?username=…) or route parameters (e.g.: test/:testId).

Additionally, you can pass any desired value via the data property inside the Route object in Angular routing as shown below:

export const appRoutes: Route[] = [
  {
    path: 'test/:testId',
    loadComponent: () => import('./test.component'),
    data: {
      permission: 'admin',
    },
  },
];
Enter fullscreen mode Exit fullscreen mode

ActivatedRoute

In all scenarios, you will start by injecting the ActivatedRoute into your component. This class gives access to the route on which your component is defined.

 

private activatedRoute = inject(ActivatedRoute);
Enter fullscreen mode Exit fullscreen mode

Within this class, you have two options for retrieving your route parameters.

Snapshot

The first option is using the snapshot object. As the name suggests, it allows you to take a snapshot of the route state and work with it.

testId = this.activatedRoute.snapshot.params['testId'];
permission = this.activatedRoute.snapshot.data['permission'];
user = this.activatedRoute.snapshot.queryParams['user'];
Enter fullscreen mode Exit fullscreen mode

Using the snapshot object provides static values, meaning that if the parameters change, you will not be notified unless you reload your component.

It is generally considered safer to choose the next option:

Observable

Alternatively, each parameter can be listened to as an observable. Although this may feel more complex, it provides the advantage of being notified when the value changes.

testId$ = this.activatedRoute.params.pipe(map((p) => p['testId']));
permission$ = this.activatedRoute.data.pipe(map((d) => d['permission']));
user$ = this.activatedRoute.queryParams.pipe(map((q) => q['user']));
Enter fullscreen mode Exit fullscreen mode

By using observables, you can subscribe to these streams (using asyncPipe or subscribe function) and receive notifications whenever the values of the parameters change. 
This allows for more dynamic and responsive behavior in your components.

Ngrx Router Store

If you are using Ngrx within your application, you might be interested in retrieving route parameters through Selectors.
First, you need to add the @ngrx/router-store npm package and include it in your bootstrapApplication function in the main.ts file:

import { provideStore } from '@ngrx/store';
import { provideRouterStore, routerReducer } from '@ngrx/router-store';

import { AppComponent } from './app.component';

bootstrapApplication(AppComponent, {
  providers: [
    //...
    provideStore({
      router: routerReducer,
    }),
    provideRouterStore()
  ],
});
Enter fullscreen mode Exit fullscreen mode

Next, Ngrx provides a getRouterSelectorfunction with a variety of selectors that you can use. You can destructure the function as follow:

import { getRouterSelectors, RouterReducerState } from '@ngrx/router-store';

// Other selectors are available:
// https://next.ngrx.io/guide/router-store/selectors
export const {
    selectQueryParam,
    selectRouteParam,
    selectRouteDataParam, 
} = getRouterSelectors();
Enter fullscreen mode Exit fullscreen mode

Finally, within your component, you can access your route parameter properties as follows:

testId$ = this.store.select(selectRouteParam('testId'));
permission$ = this.store.select(selectRouteDataParam('permission'));
user$ = this.store.select(selectQueryParam('user'));
Enter fullscreen mode Exit fullscreen mode

You end up with observables and you must subscribe to them to get notified.

RouterInput in Angular v16

Angular v16 was released with a lots of new features aiming to improve the developer experience (DX). One of these features is RouterInput, which allows you to retrieve route information through inputs.

If you haven't yet explored AngularChallenges or completed the router input challenge, I encourage you to do so now or at a later time to practice using this new API. You can find the challenge details here: AngularChallenges - Router Input.

To take advantage of RouterInput, you need to update your route provider in the main.ts file as follows:

import { provideRouter, withComponentInputBinding } from '@angular/router';

bootstrapApplication(AppComponent, 
  providers: [provideRouter(appRoutes, 
      withComponentInputBinding() // 👈
    )]
)
Enter fullscreen mode Exit fullscreen mode

With the updated route provider, you can now listen to route parameters through input bindings in your component:

@Input() testId!: string;
@Input() permission!: string;
@Input() user!: string;
Enter fullscreen mode Exit fullscreen mode

Notes:

  • if the testId input changes, your component will be notified (as an observable stream).
  • Router Inputs are only accessible within the routed component. If you need to access these parameters within a child component, you can use one of the methods mentioned earlier or pass the input through input binding between the parent and child components.
  • If you prefer a more descriptive decorator name, you can remap it in its definition as follow:
import {Input as RouterInput} from '@angular/router'

export class Component {
 @RouterInput() testId!: string;
}
Enter fullscreen mode Exit fullscreen mode

Feel free to explore and test your new skill on my Angular challenge #22, and enjoy experimenting with its capabilities in your projects.

You can find me on Twitter or Github.Don't hesitate to reach out to me if you have any questions.

Top comments (3)

Collapse
 
rensjaspers profile image
Rens Jaspers

Nice article!

I recently read an interesting article by Netanel Basal about using DI functions to get route params.

You create a reusable 'DI function' like this:

// get-route-param.ts
import { inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map } from 'rxjs/operators';

export function getRouteParam$(key: string) {
  return inject(ActivatedRoute).params.pipe(
    map((params) => params[key])
  }
}
Enter fullscreen mode Exit fullscreen mode

And then use it in your component:

@Component({
  ...
})
export class MyComponent {
  id$ = getRouteParam$('id');
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
achtlos profile image
thomas

indeed, you can factorize it like this if you want to reuse it. Be careful because, it needs to always be injected inside an injection context.

Collapse
 
rensjaspers profile image
Rens Jaspers

Be careful because, it needs to always be injected inside an injection context.

Good point! :-)