In this tutorial, let us look at how to pass and access the Optional or query parameters in Angular. Query parameters allow you to pass optional parameters like page number to the component. In this tutorial, we look at how to pass the query parameters using the queryParams
directive. We then look at how to retrieve the parameter in the component using the ActivatedRoute
Service.
Applies to: Angular 2 to the latest edition of i.e. Angular 8. Angular 9, Angular 10, Angular 11, Angular 12, Angular 13, Angular 14
Table of Contents
What are query parameters
Query parameters are optional parameters that you pass to a route. The query parameters are added to the end of the URL Separated by Question Mark
For Example
1 2 3 | /product?page=2 |
where page=2
is the query parameter
The above URL is an example of paginated product list, where URL indicates that second page of the Product list is to be loaded.
Difference between Query parameter and Route parameter
The route parameters are required and is used by Angular Router to determine the route. They are part of the route definition.
For Example, when we define the route as shown below, the id
is the route parameter.
1 2 3 4 | { path: 'product', component: ProductComponent } { path: 'product/:id', component: ProductDetailComponent } |
The above route matches the following URL The angular maps the values 1 & 2 to the id
field
1 2 3 4 5 6 | URL /product matches => path: 'product' /product/1 matches => path: 'product/:id' /product/2 matches => path: 'product/:id' |
The Router will not navigate to the ProductDetailComponent
route, if the id
is not provided. It will navigate to ProductComponent
instead. If the product
route is not defined, then it will result in a error.
However, the query parameters are optional. The missing parameter does not stop angular from navigating to the route. The query parameters are added to the end of the URL Separated by Question Mark
Route Parameters or Query Parameters?
- Use route parameter when the value is required
- Use query parameter, when the value is optional.
How to use Query Parameters
The Query parameters are not part of the route. Hence you do not define them in the routes array like route parameters. You can add them using the routerlink
directive or via router.navigate
method.
Passing Query Parameters
Use the queryParams
directive to add the query parameter. Use this directive along with the routerlink
directive as shown below
1 2 3 | <a [routerLink]="['product']" [queryParams]="{ page:2 }">Page 2</a> |
The router
will construct the URL as /product?pageNum=2
You can pass more than one Query Parameter as shown below
1 2 3 | <a [routerLink]="['product']" [queryParams]="{ val1:2 , val2:10}">Whatever</a> |
The router will construct the URL as /product?val1=2&val2=10
You can also navigate programmatically using the navigate method of the Router service as shown below
1 2 3 4 5 | goToPage(pageNum) { this.router.navigate(['/product'], { queryParams: { page: pageNum } }); } |
Reading Query Parameters
Reading the Query parameters is similar to reading the Router Parameter. There are two ways by which you can retrieve the query parameters.
Note that queryParams is deprecated. It is replaced by the queryParamMap.
Using queryParamsMap observable
The queryParamsMap
is a Observable
that contains a map of the query parameters available to the current route. We can use this to retrieve values from the query parameter. The queryParamsMap
is accessible via ActivatedRoute
Hence, we need to inject the ActivatedRoute
in the constructor of the component/service,where we want to read the query parameter as shown below
1 2 3 4 5 | constructor(private Activatedroute:ActivatedRoute, private router:Router){ } |
You can subscribe to the queryParamMap
of the ActivatedRoute
, which returns the
observable of type ParamMap. We can then use the get
method to read the query parameter as shown below.
1 2 3 4 5 6 | this.sub = this.Activatedroute.queryParamMap .subscribe(params => { this.pageNum = +params.get('pageNum')||0; }); |
Using snapshot.queryParamMap property
You can also read the value of the query parameter from queryParamMap
using the snapshot
property of the ActivatedRoute
as shown below
1 2 3 | this.Activatedroute.snapshot.queryParamMap.get('pageNum')||0;; |
Remember, the router populates the snapshot, when the component loads for the first time. Hence you will read only the initial value of the query parameter with the snapshot property. You will not be able to retrieve any subsequent changes to the query parameter.
queryParamsHandling
The query parameter is lost when the user navigates to another route.
For Example, if user navigates to the product page with route /product?pageNum=2
then he navigates to the product detail page, the angular removes the query parameter from the url. This is the default behaviour
You can change this behavior by configuring the queryParamsHandling strategy. This Configuration strategy determines how the angular router handles query parameters, when user navigates away from the current route. It has three options
queryParamsHandling : null
This is default option. The angular removes the query parameter from the URL, when navigating to the next..
1 2 3 | this.router.navigate(['product'], { queryParams: { pageNum: this.pageNo + 1 }, queryParamsHandling :null} ); |
1 2 3 | <a [routerLink]="['product']" [queryParams]="{ pageNum:2 }">Page 2</a> |
queryParamsHandling : preserve
The Angular preserves or carry forwards the query parameter of the current route to next navigation. Any query parameters of the next route are discarded
1 2 3 | this.router.navigate(['product'], { queryParams: { pageNum: this.pageNo + 1 }, queryParamsHandling :"preserve"} ); |
1 2 3 | <a [routerLink]="['product']" [queryParams]="{ pageNum:2 }" queryParamsHandling="preserve">Page 2</a> |
queryParamsHandling : merge
The Angular merges the query parameters from the current route with that of next route before navigating to the next route.
1 2 3 | this.router.navigate(['product'], { queryParams: { pageNum: this.pageNo + 1 }, queryParamsHandling :"merge"} ); |
1 2 3 | <a [routerLink]="['product']" [queryParams]="{ pageNum:2 }" queryParamsHandling="merge">Page 2</a> |
Note that preserveQueryParams is DEPRECATED
Query Params Example
Let us build a small application to demonstrate the use of Query parameters
Let us update the app that we have built in the Passing Parameters to Route tutorial. You can download the code from gitHub. From the folder “Parameters” and the Final code at “QueryParameters”
AppComponent
app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Routing Module - Query Parameters'; pageNum=0; } |
app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#"><strong> {{title}} </strong></a> </div> <ul class="nav navbar-nav"> <li><a [routerLink]="['home']">Home</a></li> <div class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Page No" [(ngModel)]="pageNum"> </div> </div> <li class="nav"><a [routerLink]="['product']" [queryParams]="{ pageNum: pageNum }">Product</a></li> <li><a [routerLink]="['contact']">Contact us</a></li> </ul> </div> </nav> <router-outlet></router-outlet> </div> |
We have defined the pageNum
variable in the component. An input box for the pageNum
is provided, so that the user can change the page no.
The AppComponent
has the navigation Menu. It contains the link to the product page. The link is created using the routerlink
directive. The routerlink
directive contains the queryParams
directive, where we pass the pageNum
to "pageNum"
variable.
1 2 3 | <li class="nav"><a [routerLink]="['product']" [queryParams]="{ pageNum: pageNum }">Product</a></li> |
The Angular will construct the URL as /product?pageNum=2
Product Component
The ProductComponent
does not display any products. But it displays the query parameters received
product.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router} from '@angular/router'; @Component({ templateUrl: './product.component.html', }) export class ProductComponent implements OnInit { pageNo=0; snapshotPageNo=0; constructor(private Activatedroute:ActivatedRoute, private router:Router){ } ngOnInit() { // the following code works but is DEPRECATED // this.snapshotPageNo =this.Activatedroute.snapshot.queryParams['pageNum']||0; // this.Activatedroute.queryParams // .subscribe(params => { // this.pageNo = +params['pageNum']||0; // console.log('Query params ',this.pageNo) // }); this.snapshotPageNo =+this.Activatedroute.snapshot.queryParamMap.get('pageNum')||0;; this.Activatedroute.queryParamMap .subscribe(params => { this.pageNo = +params.get('pageNum')||0; console.log('Query params ',this.pageNo) }); } nextPage() { this.router.navigate(['product'], { queryParams: { pageNum: this.pageNo + 1 }} ); } } |
product.component.html
1 2 3 4 5 6 7 8 | <h1>Product Page</h1> <p>Current Page No <strong> {{pageNo}} </strong></p> <p>snapshot Page No <strong> {{ snapshotPageNo }} </strong></p> <button (click)="nextPage()">Next Page</button> |
First, we have injected both ActivatedRoute
and Router
Service in the constructor of the ProductComponent
1 2 3 4 5 6 | constructor(private Activatedroute:ActivatedRoute, private router:Router){ } |
Next, in the ngOnInit lifecycle hook, we use the Activatedroute.snapshot
method to retrieve the pageNum
and update the snapshotPageNo
variable.
We also subscribe to the queryParams
property. We are updating our local variable pageNo
with page number obtained from the Queryparams
In our template, we display both snapshotPageNo
pageNo
variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 | ngOnInit() { this.snapshotPageNo = this.Activatedroute.snapshot.queryParams['pageNum'] || 0; this.Activatedroute.queryParams .subscribe(params => { this.pageNum = +params['pageNum']||0; console.log('Query params ',this.pageNum) }); } |
We also have nextPage
method.
1 2 3 4 5 | nextPage() { this._router.navigate(['./'], { queryParams: { pageNum: this.pageNum + 1 }, relativeTo: this._Activatedroute } ); } |
Here we are using the router.navigate
method to navigate to the next page. This actually does not change route as we are already in the page. The angular router does not re create the component, but since we have subscribed to the Query parameters, we will be notified of the change in page Number. The pageNum
variable is updated to the new value, while the snapshotPageNo
does not change
Other Components
app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; import { HomeComponent} from './home.component' import { ContactComponent} from './contact.component' import { ProductComponent} from './product.component' import { appRoutes } from './app.routes'; @NgModule({ declarations: [ AppComponent,HomeComponent,ContactComponent,ProductComponent ], imports: [ BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(appRoutes) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } |
app.routes.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import { Routes } from '@angular/router'; import { HomeComponent} from './home.component' import { ContactComponent} from './contact.component' import { ProductComponent} from './product.component' export const appRoutes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'contact', component: ContactComponent }, { path: 'product', component: ProductComponent }, { path: '', redirectTo: 'home', pathMatch: 'full' }, ]; |
home.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 | import {Component} from '@angular/core'; @Component({ template: `<h1>Welcome!</h1> <p>This is Home Component </p> ` }) export class HomeComponent { } |
contact.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 | import {Component} from '@angular/core'; @Component({ template: `<h1>Contact Us</h1> <p>TekTutorialsHub </p> ` }) export class ContactComponent { } |
Testing the Application
Run the application, enter the page Number and click on the Product Link.
thank you very much you explained really nice
I really wanna thank you for your straightforward explanation, great.
When you are doing so much of work, please add screen shots so that we can understand better just by looking to the screen shots. This would be very valuable addition and you can trust me on this :).
Yes !! you are right adding screenshot are best for us to understand output while reading article..
Thank you so much for explaining it.
how can we pass the query params to external application??
I want to pass jwt and user id from angular to the php page so how can i achieve this ?
Please read the
https://www.tektutorialshub.com/angular/angular-httpclient/
https://www.tektutorialshub.com/angular/angular-http-get-example-using-httpclient/
https://www.tektutorialshub.com/angular/angular-http-post-example/
https://www.tektutorialshub.com/angular/angular-pass-url-parameters-query-strings/
https://www.tektutorialshub.com/angular/angular-httpheaders/
https://www.tektutorialshub.com/angular/angular-httpclient-http-interceptor/
you have to pass these information through HTTP request header(jwt token) and body(user info) section and not through query param.
your next (“Navigation Between Routes”) is not working its showing 404 error. hence you write a very nice, good and valuable blog. i just read only angular2 and you explain in very good manner with good coding style. keep it up and also enable the page as i mentioned earlier. Please available on you tube also with live example. if you have time to get in touch with your user try to come on skype that will more valuable to your user to solve there query.
Once again lots of thanks to write this blog.
Thanks