How To Use Query Parameters In Angular

Introduction

 
In this article, we'll understand the Query Parameters feature in Angular in detail. We'll see how we can pass query parameters while navigating from one route to another and how to access those parameters.
 

Query Parameters 

 
The query parameters feature in Angular lets you pass the optional parameters while navigating from one route to another. When you pass a query parameter to a specific route, it looks something like this,
 
http://localhost:4200/orders?category=watches
 
As you can see in the above URL, the category is the query parameter and watches is its value.
 

How to pass the Query Parameters?

 
There are two primary ways to pass query parameters.
 
Using Router service
 
The Angular router service comes bundled with the navigate method which lets you move from one route to another. The first argument to this method is an array of URL fragments that represents a route. This method also accepts a second argument in form of an object. This object could be utilized to specify the query params.
 
Let's understand this in detail with the help of the URL mentioned in the above section. Let's say that we wish to navigate to the orders page with category as the query parameter and watches as its value. We can do this using the following code snippet,
  1. filterWatches() {  
  2.     this.router.navigate(['/orders'], { queryParams: { category: 'watches' } });  
  3. }   
As you can see in the above code snippet, the parameters ['/orders']  and  { queryParams: { category: 'watches' } } passed to the navigate method lets Angular know that it needs to navigate to the orders route with category = watches in the query parameters.
 
You could also pass multiple parameters by adding multiple key-value pairs to queryParams object.
  1. filterWatches(): void {  
  2.     this.router.navigate(['/orders'], { queryParams: { category: 'watches', type: 'analog' } });  
  3. }  
The above code will pass two query parameters, category and type to the orders route and the URL will look like this,
 
http://localhost:4200/orders?category=watches&type=analog
 
Preserving or merging query parameters
 
In our first example, when we moved to orders it sends a query parameter category to the route. However, this parameter is lost when we try to navigate away from this page.
 
However, if we wish to preserve; i.e. persist the query params we could do that by adding queryParamsHandling option to navigate the method of the next route.
  1. home(): void {  
  2.     this.router.navigate(['/home'], { queryParamsHandling: 'preserve' });  
  3. }  
The above code will result in the following URL,
 
http://localhost:4200/home?category=watches 
  
If the home route has its own query parameter then we could use merge instead of  preserve.
  1. home() {  
  2.     this.router.navigate(['/home'], { queryParams: { message: 'hello' }, queryParamsHandling: 'merge' });  
  3. }  
The resulting URL will look like this,
 
http://localhost:4200/home?category=watches&message=hello
 
Using RouterLink Directive
 
You could also use queryParams directive to pass the query parameters, instead of Router service. 
  1. <a [routerLink]="['/order']" [queryParams]="{ category: 'watches'}">  
  2.   Orders  
  3. </a>  
You could also use queryParamsHandling directive to specify the preserve or merge option.
  1. <a   
  2.   [routerLink]="['/order']"   
  3.   [queryParams]="{ category: 'watches'}"   
  4.   queryParamsHandling="preserve">      
  5.     Orders      
  6. </a>

How to access the Query Parameters?

 
In order to access the parameters, we need to utilize the ActivatedRoute service. The ActivatedRoute service consists of queryParams property which holds an observable. Subscribing to this observable will give you access to query parameters passed in the URL. Let's understand this using the orders route example,
 
The first thing we need to do is to inject the ActivatedRoute route inside the component where we wish to access the parameters.
  1. import { Component, OnInit } from '@angular/core';  
  2. import { ActivatedRoute } from '@angular/router';  
  3.   
  4. @Component({...})  
  5. export class OrdersComponent implements OnInit {  
  6.   constructor(private route: ActivatedRoute) { }  
  7.   
  8.   ngOnInit(): void {  
  9.     ...  
  10.   }
  11. }  
Next, we'll subscribe to the queryParams property,
  1. ngOnInit(): void {  
  2.     this.route.queryParamMap.subscribe(params => console.log(params)); // output: 
  3. }  
http://localhost:4200/orders?category=watches  
 
For the above URL output in the console will look something like this,
 
 

Passing complex data types using Query Parameters

 
In order to pass complex data types like objects or arrays, we need to first convert them into strings using the JSON.stringify method. 
 
Let's take a look at a quick example,
  1. filterWatches() {  
  2.     const countries = ['India''Japan''France''Germany'];
  3.     this.router.navigate(['/orders'], { queryParams: { countries: JSON.stringify(countries) } });
  4. }  
The steps to access the parameter are the same the only difference is you will receive the array in string format.
  1. ngOnInit(): void {  
  2.     this.route.queryParamMap.subscribe((params: any) => console.log(params));  
  3. }  
The above code will produce the following output in the console.
 
 
In order to access the array, you need to use the JSON.parse method. 
  1. ngOnInit(): void {  
  2.     this.route.queryParamMap.subscribe((params: any) => console.log(JSON.parse(params.params.countries)));  
  3. }  
The above code snippet will result in the following output,
 
 
You could follow the same steps mentioned for the array in order to send objects using the query parameters.
 

Summary

  • Query parameters can be used to pass values from one route to another.
  • Query parameters can be passed using the Router service or the queryParams directive.
  • To access query parameters ActivatedRoute service needs to be used.
  • Complex data types like arrays of objects can also be passed using query parameters however these data types need to be stringified before being passed.