How to pass data in Angular router component 14 . ?

In previous articles, we have learned, how to implement routing and how to configure routing in an angular application in detail. In part two on Angular routing, we will learn how to pass data in angular route between components. We had upgrade the article, as current Angular 14 is running.

In this tutorial, we’ll cover, How to pass data while navigating from one route to another, different approach of passing data and adding routerLink directive to the HTML anchor elements.


Setting up Angular Route parameters project

Let’s first create an Angular project and a list of components that we need to implement the Angular route query params example.

ng new angular-route-app
cd angular-route-app

#Is optional UI library
ng add @ng-bootstrap/ng-bootstrap

We use the ng-bootstrap library for this example, it is optional and if you want how to install bootstrap in the angular project, then check our previous tutorial on it.

When building a scalable web application, then we need to send and retrieve data via routing. Let’s generate a couple of components to use for navigation on our previous example of routing articles 1.

ng generate component home
ng generate component hotels
ng generate component hotel
ng generate component about
ng generate component navbar

In Angular there are different approaches to sharing data between components, we had a complete tutorial on it, and there are other options than Router, if you are interested then please check it.


Different options for Passing Data in the Angular route

Here we had listed some of approaches to passing data over the Angular route object.

  1. Using routerLink directive
  2. Using navigate method from Router object
  3. Dynamic data using state object inside navigate method.
  4. Dynamic data using queryParams directive
  5. Static data using data property

Let demonstrate abstract example and later we’ll create complete project for passing data via Route object.

Angular route Parameters
Angular route Parameters

On above a screenshot, just look at URL we can see that

http://localhost:4200/hotels/1?by=edupala.com

This URL has following parts

  1. http://localhost:4200/ is Server location
  2. hotels/ is Route Path
  3. 1is dynnamic data is Angular route parameters
  4. ?by=edupala.com after question mark is Angular route query params

Example 1: To achive above data passing, let use Angular routerlink with params and Angular Route query Params as below.

<button [routerLink]="['/hotels/' + '1']" [queryParams]="{ by: 'edupala.com' }">
  Detail
</button>

I had used static data, but we can add dynamic data also. we can achieve same using Angular router object navigate method with queryParams.

 this.router.navigate(['/hotels/' + id], {
      queryParams: { by: 'edupala.com' },
  });

<hr />

Example 2 Passing data via Route object using state object, unlike above examples, data pass via state object is not shown in URL.

 this.router.navigate(['/about'], {
      state: {
        frontEnd: JSON.stringify({ framwork: 'Angular', version: '14' }),
        site: 'edupala.com',
      },
 });

Passing Static data during Routing configuration

{ path: 'about', component: AboutComponent, data :{ id:'1', name:"Angular"} }

We can retrieve this static data via ActivatedRoute object in OnInt interface

ngOnInit() {
      this.activatedroute.data.subscribe(data => {
          console.log(data);
      })
}

Pass data in Angular route using Route parameters

Above is abstract of how we can pass data via Routing, Now let demonstrate complete project on it. Routing is not only for navigating between components, we can also pass some data to the navigated components. For example, we have a list of employees in components, and by clicking on each employee we want to show his or her details. In route navigate to employee details we can pass employee id on the route.

http://localhost:4200/employees/2

Where 2 is Angular route parameters, which we pass to destine route component.

Angular allows us to navigate between different components mainly using two approaches.

  1. First, we can use the router link directive in a template
  2. Second router object in the typescript component.

We will demonstrate router navigation using both approaches on the following link.

http://localhost:4200/about
http://localhost:4200/hotels/
http://localhost:4200/hotels/id

We have already created routing.module.ts  and imported the routing module in app.module.ts  in the previous example. Edit app-routing.module.ts to add a new routing for hotels and their children’s routes. We have hotels and its children route with hotels/: id. The slash in a route path is a dynamic value where we are passing hotel id.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about/about.component';
import { HomeComponent } from './home/home.component';
import { HotelComponent } from './hotel/hotel.component';
import { HotelsComponent } from './hotels/hotels.component';


const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'hotels', component: HotelsComponent },
  { path: 'hotels/:id', component: HotelComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Edit navbar.component.html to include a new route for hotels, login, and hotels/id.

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <button
    class="navbar-toggler"
    type="button"
    data-toggle="collapse"
    data-target="#navbarSupportedContent"
    aria-controls="navbarSupportedContent"
    aria-expanded="false"
    aria-label="Toggle navigation"
  >
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item"><a class="nav-link" [routerLink]="['/']">Home</a></li>
      <li class="nav-item"><a class="nav-link" [routerLink]="['/about']">About</a></li>
      <li class="nav-item"><a class="nav-link" [routerLink]="['/hotels']">Hotels</a></li>
    </ul>
  </div>
</nav>

We have used routerLink directive in the navbar component to navigating to about and hotels components. The routerLink directive points to the path of the component we want to visit. This directive can be applied to any element, although it is typically applied to button and anchor elements

pass data in angular route obect
Pass data in Angular router directive

Using a state object of navigate() the method of Angular router object to pass data between components

Angular allows different ways of passing data between components. We will first learn and demonstrate the state object of navigate() method, this support came since the release of Angular 7.2. We want to send data from home to about components using the state object as shown in the above picture. When a user clicks on the send button in the home component it will call the sendRouteObject () method. This method sends data as an object and navigates to about component. Let edit home.component.ts file

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

@Component({
  selector: 'app-home',
  template: ` <div class="container">
    <div class="row my-1">
      <div class="col-md-6">
        <p>1. In template, route to hotels/id where id is 2</p>
      </div>
      <div class="col-md-4">
        <button
          class="btn btn-primary"
          [routerLink]="['/hotels/' + '1']"
          [queryParams]="{ by: 'edupala.com' }"
        >
          Navigation using RouterLink in template
        </button>
      </div>
    </div>
    <div class="row my-1">
      <div class="col-md-6">
        <p>2. Programmatically route to hotels with params id</p>
      </div>
      <div class="col-md-4">
        <button class="btn btn-primary" (click)="routeToHotelId(2)">
          Navigation using router object in typescript
        </button>
      </div>
    </div>

    <div class="row my-1">
      <div class="col-md-6">
        <p>3. Send data from search to about component.</p>
        <p>
          {{
            "{ site: 'edupala.com' frontEnd: { name: Angular version: 14 } }"
          }}
        </p>
      </div>
      <div class="col-md-4">
        <button class="btn btn-primary" (click)="sendRouteObject()">
          Route to aboute component with state data
        </button>
      </div>
    </div>
  </div>`,
  styleUrls: ['./home.component.scss'],
})
export class HomeComponent {
  constructor(private router: Router) {}

  routeToHotelId(id: number) {
    this.router.navigate(['/hotels/' + id], {
      queryParams: { by: 'edupala.com' },
    });
  }

  sendRouteObject() {
    this.router.navigate(['/about'], {
      state: {
        frontEnd: JSON.stringify({ framwork: 'Angular', version: '14' }),
        site: 'edupala.com',
      },
    });
  }
}

The navigated method is one of the most used methods of router objects. The navigate takes an argument which is a URL to navigate to the new route. We can also pass data via state object in the navigate() method. In our example state object, we have two fields, a frontend object which we have to use JSON.stringify, and site as a simple variable we can pass directly.


Reading state object data in the navigate() method.

Once we navigate to the requested component. At the activated route component, we can receive data as below and add the following code in the constructor object.

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

@Component({
  selector: 'app-about',
  template: ` <h4>About works!</h4>
    <div *ngIf="data.frontEnd">
      <p>
        Route state object data from homeomponent:
        <strong>
          Data: {{ data.frontEnd?.framwork }} -
          {{ data.frontEnd?.version }} Site: {{ data.site }}
         </strong>
      </p>
    </div>`,
  styleUrls: ['./about.component.scss'],
})
export class AboutComponent {
  data: any = {};
  routeState: any;

  constructor(private router: Router) {
    if (this.router.getCurrentNavigation()?.extras.state) {
      this.routeState = this.router.getCurrentNavigation()?.extras.state;
      if (this.routeState) {
        this.data.frontEnd = this.routeState.frontEnd
          ? JSON.parse(this.routeState.frontEnd)
          : '';
        this.data.site = this.routeState.site ? this.routeState.site : '';
      }
    }
  }
}

Using Route params: To pass data in Angular route

Angular routes can be more flexible and we can pass data parameters to components in the routes as part of the URL path, for example, hotels/:id. Where id is the dynamic value of hotel id of hotel records, to demonstrate route params, let’s first create a hotel.service.ts class containing dummy hotel records and methods to manage the hotel records.

ng generate service hotels/hotel
import { Injectable } from '@angular/core';
import { IHotel } from '../Models/hotel';

@Injectable({
  providedIn: 'root'
})
export class HotelService {
  private hotels: IHotel[] = [
    { id: 1, name: 'Taj Hotel', country: 'India' },
    { id: 2, name: 'Trump', country: 'United State' },
    { id: 3, name: 'Hotel Oberoi', country: 'India' }
  ];

  getHotels() {
    return this.hotels;
  }

  getHotel(id: number) {
    return <IHotel>this.hotels.find((h: any) => h.id === id);
  }

  updateHotel(id: number, hotelData: { name: string, country: string }) {
    const hotel = this.hotels.find((h) => h.id === id);

    if (hotel) {
      hotel.name = hotelData.name;
      hotel.country = hotelData.country;
    }
  }
}

As we are learning Routing, the above service is a simple example, if you want to learn more about how Angular services. Then check on the tutorial on What is the angular service and how to implement it .?

Angular Route parameters
Angular Route parameters


In the hotels component, we have a list of all hotel records and the router-outlet. As the hotels component itself is a child component, we need a nested router-outlet as a place where we render the child element of the hotels component. Edit hotels.component.ts file

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { IHotel } from '../Models/hotel';
import { HotelService } from '../services/hotel.service';

@Component({
  selector: 'app-hotel',
  template: `<div class="container">
    <div *ngIf="hotel">
      <div class="form-group">
        <label for="name">Hotel Name</label>
        <input
          type="text"
          id="name"
          class="form-control"
          [(ngModel)]="hotel.name"
        />
      </div>
      <div class="form-group">
        <label for="status">Country</label>
        <select id="status" class="form-control" [(ngModel)]="hotel.country">
          <option value="India">India</option>
          <option value="United State">United State</option>
        </select>
      </div>
    </div>
  </div>`,
  styleUrls: ['./hotel.component.scss'],
})
export class HotelComponent implements OnInit {
  hotel: IHotel = { name: '', country: '' };
  name = '';
  country = '';

  constructor(
    private route: ActivatedRoute,
    private hotelService: HotelService
  ) {}

  ngOnInit() {
    let id = +this.route.snapshot.params['id'];

    this.route.params.subscribe((params: Params) => {
      id = +params['id'];
      this.hotel = this.hotelService.getHotel(id);
      console.log('hotel' + this.hotel);
    });
  }
}

Angular Route navigate with params via a component template.

When the user clicks on one of the edit buttons of the hotel record. We will navigate to the hotel component and in the URL path, we will pass the hotel id. Where id is a dynamic value representing hotel id and is passed on navigation URL as params

<button [routerLink]="['/hotels/' + hotel.id]">Edit</button>

Angular Route navigate with params in a component typescript.

When some operation is finished or the user clicks on some button and then we want to trigger the navigation from typescript code. In home.component.html we have a button, which on click will call a method in typescript component, which used a router object method to navigation. The router object has lots of methods, and navigation is the most used one. The navigation first parameter is a path of a component where we want to navigate.

In home.component.html
-----------------------
<button class="btn btn-primary" (click)="routeToHotelId(2)">
   Navigation using router object in typescript</button>
</button>

In home.component.ts
---------------------
routeToHotelId(id: number) {
    this.router.navigate(['/hotels/' + id]);
}

How to retrieve query param from an activated route in a component?

Once we navigate to a component, we have to retrieve query params from the activated route. Angular provides two approaches to retrieve query params at the navigate component.

  • You can read the query parameter from the activatedroute snapshot
  • The activatedRoute query parameters as an observable
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { IHotel } from '../Models/hotel';
import { HotelService } from '../services/hotel.service';

@Component({
  selector: 'app-hotel',
  template: `<div class="container">
    <div *ngIf="hotel">
      <div class="form-group">
        <label for="name">Hotel Name</label>
        <input
          type="text"
          id="name"
          class="form-control"
          [(ngModel)]="hotel.name"
        />
      </div>
      <div class="form-group">
        <label for="status">Country</label>
        <select id="status" class="form-control" [(ngModel)]="hotel.country">
          <option value="India">India</option>
          <option value="United State">United State</option>
        </select>
      </div>
    </div>
  </div>`,
  styleUrls: ['./hotel.component.scss'],
})
export class HotelComponent implements OnInit {
  hotel: IHotel = { name: '', country: '' };
  name = '';
  country = '';

  constructor(
    private route: ActivatedRoute,
    private hotelService: HotelService
  ) {}

  ngOnInit() {
    let id = +this.route.snapshot.params['id'];  OR

    this.route.params.subscribe((params: Params) => {
      id = +params['id'];
      this.hotel = this.hotelService.getHotel(id);
      console.log('hotel' + this.hotel);
    });
  }
}

The snapshot from the ActivatedRoute to read our parameters in the ngOnInit and use when we loaded a component from another component. If we need to load the same component with different parameters in the same component then it is recommended that we do not rely on the snapshot.

As a snapshot call once and the only URL will update. Instead, we can treat the parameters and query parameters as observable, just like service calls and HTTP requests. This way, the subscription will get triggered each time the URL changes, allowing us to reload the data rather than relying on the snapshot.

Note: We have comments, instead of param observable, we can use router paramMap observable.


Angular route navigate with parameter using queryParams property

We can also pass optional query parameters using the [queryParams] directive along with [routerLink] to pass query parameters in URL.  In URL queryparams with optional parameters, this is indicated by after question marks.

<button [routerLink]="['/hotels', hotel.id]" 
    [queryParams]="{by: 'edupala'}">
    Country detail
</button>
// localhost:8100/hotels/2?by=edupala

// http://localhost:4200/countries/1?by=edupala.com
someMethod(hotel: IHotel) {
   this.router.navigate(['/hotels', hotel.id], 
    {queryParams:{by:'edupala'}});
}

To retrieve optional parameters at the routed component use the queryParams observable instead of the params observable of activatedRoute.

 ngOnInit() {
     this.route.queryParams.subscribe( (param.) => {
 	let data = params.by;
     });
 }
Check articles on the best and latest 2022, and 2021 Angular books to read for your journey from beginner to advanced level. BEST BOOK ON ANGULAR 2022 – 2021

Conclusion
We have completed how-to pass data via the Angular route. Use a snapshot to read data from the route object only when we navigate from another component. Snapshot is one time read, not recommended to load the same component with a different parameter. Instead, use params observable to get the latest update value of params from the route object.

 I hope you had learned something, if so then please share it with others and on social networks, this will encourage me to add more content. Follow me on my GitHub collection, I had code on Angular, react and Ionic framework, but this Radio example is not on Github.com

Related Articles

2 thoughts on “How to pass data in Angular router component 14 . ?”

  1. A motivating discussion is worth comment. I believe that you need to publish more about this subject matter, it may not be a taboo matter but generally folks don’t speak about such subjects. To the next! Cheers!!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top