Saturday, August 27, 2022

Angular Route Parameters - Setting and Fetching

In this post we’ll see how to pass and retrieve route parameters in Angular routing.


Route parameters in Angular

In our web apps we do need to navigate to a specific resource. For example we want the details of a specific account number then we can navigate to that account number by using URL- /account/A1001 or to another account by using URL- /account/A1002.

It is not practical to hardcode the path segment for each account number, you will use a route parameter instead that acts as a placeholder. Value passed for the placeholder becomes the value of the route parameter.

In a route that takes a parameter, route parameter is specified by prefixing it with a colon. So the route definition will be like- /route/:routeparam

You can pass more than one route parameter too- /route/:param1/:param2/:param3

For example if you have to a give route definition for a route- /account/A1001 where /A1001 part represents an account number and should be passed as a route parameter.

{path: 'account/:acctno', component: COMPONENT_NAME}

Passing Route parameters in Angular

1. You can pass route parameters with RouterLink directive. For a dynamic link, pass an array of path segments (which includes path and route parameters). For example

[routerLink]="['/account', accountnumber]"     

generates a link to /account/A1001 or to /account/A1002 based on what is passed as value for the string variable accountnumber.

2. You can also pass route parameters programmatically using Router.navigate() method. For example onAccountClick() method is called with account number as argument and then it creates a URL with route parameter using navigate() method. Here account number gets added as a route parameter to the current route.

onAccountClick(accountNo: string){
  this.router.navigate([accountNo], {relativeTo:this.route});
}

Retrieving route parameters in Angular

To extract the parameter, params observable of the ActivatedRoute interface is used and we subscribe to it so that when ever there is a change in the route parameter it is extracted into a variable.

this.route.params.subscribe((params: Params)=> this.acctNo = params['acctno']);

Here value passed in acctno route parameter is assigned to acctNo variable. You can also extract parameter from the route using the current snapshot of the route.

this.acctNo = this.route.snapshot.params['acctno'];

Route parameters in Angular example

In the example we show user a list of account numbers. Then the details of the account number, that is clicked, are showed using a separate component. In this scenario you can pass the clicked account number as route parameter.

Here are the route definitions for the routes. Here AccountsComponent displays all the account numbers for a user and AccountComponent shows details for the selected account number.

const routes: Routes = [
                        {path: 'home', component: HomeComponent},                  
                        {path: 'account', component: AccountsComponent},
                        {path: 'account/:acctno', component: AccountComponent},
                        {path: 'service', component: ServiceComponent},
                        {path: '', redirectTo:'/home', pathMatch: 'full'}                  
];

As you can see there is a route with route parameter- {path: 'account/:acctno', component: AccountComponent}

Code for menu and adding link for routes is done in the app.component.html template itself for this example.

<nav class="navbar navbar-expand-md bg-dark navbar-dark">
  <div class="container-fluid">
    <div class="collapse navbar-collapse" id="collapsibleNavbar">
      <ul class="nav navbar-nav">
        <li class="nav-item" routerLinkActive="active">
          <a class="nav-link" routerLink="/home">Home</a>
        </li>
        <li class="nav-item" routerLinkActive="active">
          <a class="nav-link" routerLink="/account">Accounts</a>
        </li>
        <li class="nav-item" routerLinkActive="active">
          <a class="nav-link" routerLink="/service">Services</a>
        </li>
      </ul>
    </div>
  </div>
</nav>
<div class="container">
  <div class="row"><p></p></div>
  <div class="row">
    <div class="col-md-12">
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

Components

We’ll concentrate here on AccountsComponent and AccountComponent for the code of other components please refer- Angular Routing Concepts With Example.

AccountsComponent (accounts.component.ts)

In the component we have an array to show account numbers and a method onAccountClick() to navigate programmatically to a route.

import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-accounts',
  templateUrl: './accounts.component.html'
})
export class AccountsComponent {
  accounts = ['A1001', 'A1002'];
  constructor(private router: Router, private route: ActivatedRoute) {}
  onAccountClick(account: string){
    this.router.navigate([account], {relativeTo:this.route});
  }
}

Two classes Router class and ActivatedRoute class are injected into the component.

  • Router class has navigate() method using which we navigate to a URL dynamically.
  • ActivatedRoute class provides access to information about the current route.

This line of code instructs Angular to navigate to the path which is relative to current route (localhost:4200/account in our example) and adds the value of account to it making it a route in this format- http://localhost:4200/account/ACCOUNT_NUMBER

this.router.navigate([account], {relativeTo:this.route});

Since we already have a route definition with a route parameter {path: 'account/:acctno', component: AccountComponent} which matches any route in this format http://localhost:4200/account/ACCOUNT_NUMBER so that’s how AccountComponent gets called.

accounts.component.html

<div class= "row">
  <div class="col-xs-4 col-md-6">
    <h2>Account Numbers</h2>
    <div class="list-group">
      <a [routerLink]="" 
        (click)="onAccountClick(account)" 
        class="list-group-item"   
        *ngFor="let account of accounts">
        {{ account }}
      </a>
    </div>
  </div>
</div>

If you want to use RouterLink directive then your template can be written as-

  <div class= "row">
  <div class="col-xs-4 col-md-6">
    <h2>Account Numbers</h2>
    <div class="list-group">
      <a [routerLink]="['/account', account]" class="list-group-item"  
        *ngFor="let account of accounts">
        
        {{ account }}
      </a>
    </div>
  </div>
</div>
  

In this case onAccountClick() method can be removed from typescript code as navigation is configured in the template itself.

AccountComponent (account.component.ts)

In this component we simulate a scenario where we have details for all the account numbers and we have to get the details for the account number which is sent as route parameter.

To extract the parameter route.params observable is used and we subscribe to it so that whenever there is a change, value of the parameter is extracted into a acctNo variable. Using the fetched account number we find the related object in the array using the find() method.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html'
})
export class AccountComponent implements OnInit{
  acctNo: string;
  account: {accountnumber: string, type: string, balance: number};
  constructor(private route: ActivatedRoute){ }
  accountDetails = [
    {
      accountnumber: 'A1001',
      type: 'Saving', 
      balance: 22000
    },
    {
      accountnumber: 'A1002',
      type: 'Checking',
      balance: 1000
    }
  ];

  ngOnInit() {
    //this.acctNo = this.route.snapshot.params['acctno'];
    this.route.params.subscribe((params: Params)=> this.acctNo = params['acctno']);
    this.account = this.accountDetails.find(e=>e.accountnumber === this.acctNo);
  }
}

Note that you can also extract parameter from the route using the current snapshot of the route. But route.params observable is preferred.

this.acctNo = this.route.snapshot.params['acctno'];

account.component.html

<h2>Account Details</h2>
<div class="row">
  <div class="col-xs-6">
    <label>Account Number: </label> {{ account.accountnumber }}
  </div>
</div>
<div class="row">
  <div class="col-xs-6">
    <label>Account Type: </label> {{ account.type }}
  </div>
</div>
<div class="row">
  <div class="col-xs-6">
    <label>Balance: </label> {{account.balance}}
  </div>
</div>

Accounts Component

Account Component

That's all for this topic Angular Route Parameters - Setting and Fetching. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Passing Query Parameters in Angular Routing
  2. Path Redirection in Angular Routing
  3. Navigate to a Route Programmatically in Angular
  4. Using RouterLinkActiveOptions to Fix Link Highlighted Problem
  5. Angular CanActivateChild Guard to protect Child Routes

You may also like-

  1. Angular Custom Two-Way Data Binding
  2. Angular ngSwitch Directive With Examples
  3. Angular @Input and @Output Example
  4. How to Add Bootstrap to Angular Application
  5. PriorityBlockingQueue in Java Concurrency
  6. Difference Between StackOverflowError and OutOfMemoryError in Java
  7. Predefined Mapper And Reducer Classes in Hadoop
  8. Passing Arguments to getBean() Method in Spring

No comments:

Post a Comment