Route parameters
- Route parameters

Original photo by Geran de Klerk on Unsplash, Angular logo by Angular PressKit / CC BY 4.0
Routing is one of the fundamental mechanisms in Angular. Its primary use is to provide a way to navigate through an application. Without it, we would be stuck on the same page forever!
Apart from navigating, routing can also be used to pass small pieces of information between routed components. This can be achieved with the use of route parameters.
There are three types of route parameters in Angular:
- required parameters,
- optional parameters, and
- query parameters.
In this article, we present how basic routing works. Then we study all three types of route parameters provided by Angular.
Let’s get started!
Routing Basics
Routing is used primarily to navigate through an application. Most single-paged applications have some sort of menu (or toolbar) so the user can navigate around.
To make navigation happen, we use the [RouterLink](https://angular.io/api/router/RouterLink) directive in the HTML of the menu. The routerLink defines the route that will be activated when the user clicks that specific option.
<div>
<ul>
<li><a [routerLink]="['/home']">Home</a></li>
<li><a [routerLink]="['/pandas']">Pandas</a></li>
</ul>
<router-outlet></router-outlet>
</div>
Let’s say we click the “Pandas” link. The URL address bar is then updated to include the activated route: htttp://localhost:4200/pandas.
The Router detects the change to the address bar and sequentially checks the list of route configuration paths for a match.
RouterModule.forRoot([
{
path: '', redirectTo: 'home', pathMatch: 'full'
},
{
path: 'home', component: HomeComponent
},
{
path: 'pandas', component: PandaListComponent
},
{
path: 'pandas/:id', component: PandaDisplayComponent
}
]);
It selects the first match it finds and then loads the specified component. The Router looks for the RouterOutlet directive, which specifies where to put the identified component.
Finally, it displays that view in the location defined by the RouterOutlet.
Route Parameters
Angular provides three different types of route parameters: required, optional, and query parameters.
Required parameters
As their name suggests, these parameters are required for the next routed component to function properly.
Required parameters must be defined as part of the route configuration.
{
path: 'pandas/:id', component: PandaDisplayComponent
}
In our previous snippet, we define a required parameter — the id of a panda. Navigating to this route requires the id so the routed component PandaDisplayComponent can load and display the selected panda.
To activate a path with a required parameter, we use the routerLink and pass the specified parameters as extra elements to the associated array.
<div *ngFor="let panda of pandas">
<a [routerLink]="['/pandas', panda.id]"> {{ panda.name }} </a>
</div>
To navigate programmatically, we would pass the parameters to Router’s navigate method, in a similar way.
constructor(private router: Router) { }
displayPanda(id: number) {
this.router.navigate(['/pandas', id]);
}
The resulting URL would look like this: http://localhost/pandas/1.
The routed component can then read that parameter from the [ActivatedRoute](https://angular.io/api/router/ActivatedRoute) and use it to display the correct panda.
constructor(private route: ActivatedRoute,
private pandaService: PandaService) { }
ngOnInit(): void {
const param = this.route.snapshot.paramMap.get('id');
if (param) {
const id = +param;
this.panda = this.pandaService.getPandaById(id);
}
}
Note, that the parameter name passed in the getter must match the name as defined in the path.
Here, we are navigating to a new route. So, we simply use the paramMap property to get a value statically. If we stayed on the same route but wanted to listen to parameter changes, we would need to subscribe to the paramMap observable instead.
ngOnInit(): void {
this.route.paramMap.pipe(
map((paramMap: ParamMap) => +(paramMap?.get('id') ?? -1)),
map((id: number) => this.pandaService.getPandaById(id))
).subscribe((panda: Panda | undefined) => (this.panda = panda));
}
Optional Parameters
Unlike required parameters, optional parameters are not mandatory. Therefore, they are not part of the route configuration.
Instead, we specify optional parameters as properties of an object, which we pass as an extra element to the associated array when activating the route.
<a [routerLink]="['/pandas', { filterTerm, sortBy }]"> Pandas </a>
The previous snippet passes an optional parameter named filterTerm.
Hint: We could have written this as
{ filterTerm: filterTerm }, but it would be redundant. We’re guessing you already know this.
Respectively, to navigate programmatically, we would similarly pass the parameters.
this.router.navigate(['/pandas', { filterTerm, sortBy }]);
The optional parameters are specified as a set of key and value pairs in a single element of the associated array. The resulting URL looks like this: http://localhost:4200/pandas;filterTerm=Bobo;sortBy=name.
It may seem a bit odd, but it’s basically the key-value pairs separated with semicolons.
This URL is bookmarkable, which means that if we copy-paste it to the address bar, the component will load with that specific filtering and sorting in place.
The routed component can then read and use the parameters.
export class PandaDisplayComponent implement OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
const filterTerm = this.route.snapshot.paramMap.get('filterTerm');
const sortBy = this.route.snapshot.paramMap.get('sortBy');
}
}
Again, if we wanted to listen for changes, we would have to subscribe to the paramMap observable instead.
ngOnInit(): void {
this.route.paramMap.subscribe((paramMap: ParamMap) => {
this.filterTerm = paramMap.get('filterTerm');
this.sortBy = paramMap.get('sortBy');
})
}
Query Parameters
Query parameters, like optional parameters, are not specified as part of the route configuration.
Instead, we specify them when activating the route with an additional directive, queryParams.
<a [routerLink]="['/pandas']"
[queryParams]="{ filterTerm, sortBy }"> Pandas </a>
To navigate programmatically, we would pass the parameters as an extra navigation object with a queryParams property. Notice that the object is not in the associated array this time!
this.router.navigate(['/pandas'], { queryParams: { filterTerm, sortBy } });
The resulting URL is http://localhost:4200?filterTerm=Bobo&sortBy=name and follows the standard URL format for query parameters. Again, this URL is bookmarkable — like with the optional parameters.
The routed component can then read and use the parameters.
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
const filterTerm = this.route.snapshot.queryParamMap.get('filterTerm');
const sortBy = this.route.snapshot.queryParamMap.get('sortBy');
}
Notice that we now use queryParamMap instead of paramMap.
Respectively, if we wanted to listen to changes, we would have to subscribe to the queryParamMap observable instead.
ngOnInit(): void {
this.route.queryParamMap.subscribe((paramMap: ParamMap) => {
this.filterTerm = paramMap.get('filterTerm');
this.sortBy = paramMap.get('sortBy');
});
}
You can find a working demo at the StackBlitz below. Don’t forget to subscribe to my newsletter for more content like this!
Optional vs. Query
At this point, you must be wondering — what’s the difference between optional and query parameters? Syntax and the resulting URL?
For sure query parameters have a more familiar URL, but apart from that, do they provide anything extra? You betcha!
With optional parameters, if we navigate back to the previous route without passing them back the parameters will be gone.
With query parameters, on the other hand, we can set queryParamsHandling and they’ll be included automatically!
<button [routerLink]="['/pandas']"
queryParamsHandling="preserve"> Back </button>