https://www.tektutorialshub.com/angular/angular-passing-parameters-to-route/
How to Pass parameters to Angular Route
Defining the Route
We can define parameter by adding forward slash followed colon and a placeholder (id) as shown below
| { path: 'product/:id', component: ProductDetailComponent } |
Now above path matches the URLs /product/1
, /product/2
, etc.
If you have more than one parameter, then you can extend it by adding one more forward slash followed colon and a placeholder
| { path: 'product/:id/:id1/:id2', component: ProductDetailComponent } |
The name id
, id1
& id2
are placeholders for parameters. We will use them while retrieving the values of the parameters.
Defining the Navigation
We, now need to provide both path and the route parameter routerLink
directive.
This is done by adding the productID
as the second element to the routerLink
parameters array as shown below
| <a [routerLink]="['/Product', ‘2’]">{{product.name}} </a> |
Which translates to the URL /product/2
OR
| <a [routerLink]="['/Product', product.productID]">{{product.name}} </a> |
Which, dynamically takes the value of id from the product object.
Retrieve the parameter in the component
Finally, our component needs to extract the route parameter from the URL
This is done via the ActivatedRoute service from angular/router module to get the parameter value
ActviatedRoute
The ActivatedRoute is a service, which keeps track of the currently activated route associated with the loaded Component.
To use ActivatedRoute
, we need to import it in our component
| import { ActivatedRoute } from '@angular/router'; |
Then inject it into the component using dependency injection
| constructor(private _Activatedroute:ActivatedRoute) |
ParamMap
The Angular adds the map all the route parameters in the ParamMap
object, which can be accessed from the ActivatedRoute
service
The ParamMap
makes it easier to work with parameters. We can use get
or getAll
methods to retrieve the value of the parameters in the component. Use the has
method to check if a certain parameter exists.
The Older version of ActivatedRoute class has a Params array which is an array of the parameter values, indexed by name. You can still use it but It is now deprecated and is replaced by the ParamMap.
There are two ways in which you can use the ActivatedRoute
to get the parameter value from the ParamMap
object.
- Using Snapshot
- Using observable
Using Snapshot
| this.id=this._Activatedroute.snapshot.paramMap.get("id"); |
The snapshot
property returns the initial value of the route. You can then access the paramsMap
array, to access the value of the id
, as shown above,
Use the Snapshot option, if you only need the initial value.
Using Observable
| this._Activatedroute.paramMap.subscribe(params => { this.id = params.get('id'); }); |
You can retrieve the value of id
by subscribing to the paramMap
observable property of the activateRoute
as shown above
Use this option if you expect the value of the parameter to change over time.
Why use observable
We usually retrieve the value of the parameter in the ngOninit life cycle hook, when the component initialised.
When the user navigates to the component again, the Angular does not create the new component but reuses the existing instance. In such circumstances, the ngOnInit
method of the component is not called again. Hence you need a way to get the value of the parameter.
By subscribing to the observable paramMap property, you will retrieve the latest value of the parameter and update the component accordingly.
The above difference is explained in our next tutorial Angular child routes tutorial.
Passing Parameters to Route: Example
Here is the complete list of code.
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 | import { Component, OnInit } from '@angular/core'; import { ProductService } from './product.service'; import { Product } from './product'; @Component({ templateUrl: './product.component.html', }) export class ProductComponent { products:Product[]; constructor(private productService:ProductService){ } ngOnInit() { this.products=this.productService.getProducts(); } } |
product.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <h1>Product List</h1> <div class='table-responsive'> <table class='table'> <thead> <tr> <th>ID</th> <th>Name</th> <th>Price</th> </tr> </thead> <tbody> <tr *ngFor="let product of products;"> <td>{{product.productID}}</td> <td><a [routerLink]="['/product',product.productID]">{{product.name}} </a> </td> <td>{{product.price}}</td> </tr> </tbody> </table> </div> |
product.service.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 | import { Observable } from 'rxjs'; import {Product} from './Product' export class ProductService{ public getProducts() { let products:Product[]; products=[ new Product(1,'Memory Card',500), new Product(2,'Pen Drive',750), new Product(3,'Power Bank',100) ] return products; } public getProduct(id) { let products:Product[]=this.getProducts(); return products.find(p => p.productID==id); } } |
product.ts
| export class Product { constructor(productID:number, name: string , price:number) { this.productID=productID; this.name=name; this.price=price; } productID:number ; name: string ; price:number; } |
In the product.component.html, we have added product.productID
as the second argument to the routerLink
parameters array.
| <a [routerLink]="['/product',product.productID]">{{product.name}} </a> |
Product Details Component
product-detail.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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router,ActivatedRoute } from '@angular/router'; import { ProductService } from './product.service'; import { Product } from './product'; @Component({ templateUrl: './product-detail.component.html', }) export class ProductDetailComponent { product:Product; id; constructor(private _Activatedroute:ActivatedRoute, private _router:Router, private _productService:ProductService){ } /* Using snapshot */ // ngOnInit() { // //This still works but is deprecated // //this.id=this._Activatedroute.snapshot.params['id']; // this.id=this._Activatedroute.snapshot.paramMap.get("id"); // let products=this._productService.getProducts(); // this.product=products.find(p => p.productID==this.id); // } /* Using Subscribe */ sub; ngOnInit() { this.sub=this._Activatedroute.paramMap.subscribe(params => { console.log(params); this.id = params.get('id'); let products=this._productService.getProducts(); this.product=products.find(p => p.productID==this.id); }); // This params is deprecated //this.sub=this._Activatedroute.params.subscribe(params => { // this.id = params['id']; // let products=this._productService.getProducts(); // this.product=products.find(p => p.productID==this.id); // //}); } ngOnDestroy() { this.sub.unsubscribe(); } onBack(): void { this._router.navigate(['product']); } } |
product-detail.component.html
| <h3>Product Details Page</h3> product : {{product.name}} price : {{ product.price}} <p> <a class='btn btn-default' (click)="onBack()">Back </a> </p> |
In the ProductDetailComponent, we have imported router
and ActivatedRoute
from the angular router module
| import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router,ActivatedRoute } from '@angular/router'; |
In the constructor, we inject the ActivatedRoute
, Router
service along with ProductService
| constructor(private _Activatedroute:ActivatedRoute, private _router:Router, private _productService:ProductService){ } |
Finally, we use ngOninit
life cycle hook to retrieve the value of the id
parameter and use that value to retrieve the details of the product.
Note that, there are two ways, by which you can retrieve the data.
Using snapshot
| ngOnInit() { //This still works but is deprecated //this.id=this._Activatedroute.snapshot.params['id']; this.id=this._Activatedroute.snapshot.paramMap.get("id"); let products=this._productService.getProducts(); this.product=products.find(p => p.productID==this.id); } |
Using Subscribe
We used snapshot method to retrieve the parameter in the ProductDetailcomponet.ts. To Subscribe to params remove the ngOnInit and replace it with the following code
We recommend you to use the subscribe method as it offers the benefit of responding to the parameter changes dynamically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ngOnInit() { this.sub=this._Activatedroute.paramMap.subscribe(params => { console.log(params); this.id = params.get('id'); let products=this._productService.getProducts(); this.product=products.find(p => p.productID==this.id); }); // This params is deprecated //this.sub=this._Activatedroute.params.subscribe(params => { // this.id = params['id']; // let products=this._productService.getProducts(); // this.product=products.find(p => p.productID==this.id); // //}); } |
The Routes
app.routing.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { Routes } from '@angular/router'; import { HomeComponent} from './home.component' import { ContactComponent} from './contact.component' import { ProductComponent} from './product.component' import { ErrorComponent} from './error.component' import { ProductDetailComponent} from './product-detail.component' export const appRoutes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'contact', component: ContactComponent }, { path: 'product', component: ProductComponent }, { path: 'product/:id', component: ProductDetailComponent }, { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '**', component: ErrorComponent } ]; |
We have added the following route to our routes array
| { path: 'product/:id', component: ProductDetailComponent }, |
Other components
app.component.ts
| import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Routing Module - Parameters Demo'; } |
app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" [routerLink]="['/']"><strong> {{title}} </strong></a> </div> <ul class="nav navbar-nav"> <li><a [routerLink]="['home']">Home</a></li> <li><a [routerLink]="['product']">Product</a></li> <li><a [routerLink]="['contact']">Contact us</a></li> </ul> </div> </nav> <router-outlet></router-outlet> </div> |
contact.component.ts
| import {Component} from '@angular/core'; @Component({ template: `<h1>Contact Us</h1> <p>TekTutorialsHub </p> ` }) export class ContactComponent { } |
home.component.ts
| import {Component} from '@angular/core'; @Component({ template: `<h1>Welcome!</h1> <p>This is Home Component </p> ` }) export class HomeComponent { } |
error.component.ts
| import {Component} from '@angular/core'; @Component({ template: `<h1>Page not found</h1> <p>This is a Error Page</p> ` }) export class ErrorComponent { } |
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 31 32 33 34 35 | 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 { ErrorComponent} from './error.component' import { ProductDetailComponent} from './product-detail.component' import { ProductService } from './product.service'; import { appRoutes } from './app.routes'; @NgModule({ declarations: [ AppComponent,HomeComponent,ContactComponent,ProductComponent,ErrorComponent,ProductDetailComponent ], imports: [ BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(appRoutes) ], providers: [ProductService], bootstrap: [AppComponent] }) export class AppModule { } |
No comments:
Post a Comment