Skip to main content

Related Articles

How to share data between components in angular

 

sharing data between unrelated components angular

Today I am going to talk about how we can make interaction between two different components in angular.

There are two main approaches that we can follow.

1. If the two components are not relative, then you can use behavioral subjects to share data and trigger the event in one component, based on the value change in another component.

2. If the component is a child component of another component, then you can share data using @Input and @output directives

Today in this chapter we will discuss on the first approach.

How you can use Behavior subject to share between two components. 

The BehaviorSubject holds the value that needs to be shared with other components.

I will explain the concept using our flower store app.

First, I will add PrimeNG text filed to the app.component.html file.

To add the text field you have to import it in app.module.ts and also in app.component.ts file


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LandingComponent } from './modules/landing/landing.component';
import { HomeComponent } from './modules/home/home.component';
import { CardModule } from 'primeng/card';
import {CheckboxModule} from 'primeng/checkbox';
import { CommonModule } from '@angular/common';
import { FormsModule }    from '@angular/forms';
import {InputTextModule} from 'primeng/inputtext';

@NgModule({
  declarations: [
    AppComponent,
    LandingComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    CardModule,
    CheckboxModule,
    CommonModule,
    FormsModule,
    InputTextModule
    
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  
Also need to import it inside app.component.ts. The ViewEncapsulation.None line need to add if you want to override PrimeNG styles inside your component.css file.


import { Component, ViewEncapsulation } from '@angular/core';
import {InputTextModule} from 'primeng/inputtext';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  encapsulation: ViewEncapsulation.None

})
export class AppComponent {
  title = 'my-flower-store';
  searchText:string='';
  

In app.component.html file I have added the PrimeNG text filed as below.


<header>
  <div class="container">
    <a href="" class="logo">My flower shop</a>
  <span [style]="{'padding-left':'10px'}" >
      <input type="text" pInputText placeholder="Search" [(ngModel)]="searchText" />
  </span>
    <nav>
      <ul>
        <li><a href="" routerLink="/">Landing</a></li>
        <li><a href="" routerLink="/home">Home</a></li>
      </ul>
    </nav>
  </div>
</header>

<div class="container">
  <router-outlet></router-outlet>
</div>
  
Now once I refresh my browser, I can see below view which has the input text filed to enter search text.

input text filed to enter search text



Now what I am trying to do is I am going to display search text in my landing.component.html file.

Here the challenge I have is my search filed is in one component (app.component.html) and my flower cards in another component (landing.component.html). These two components don’t have any relationship.

How can I get the search text value from app.component.ts to landing.component.ts.

Here comes the angel Behavior Subject to support me.

Let me explain what you need to do to share the search text value using behavior subject concept.

First, I am going to generate the service class. To generate go inside the service folder and type below command.

>ng g s data

‘g’ and ‘s’ means generate service and then the ‘data’ is service name. This will create two files inside src/app/service folder


data.service.spec.ts and data.service.ts in src/app/service folder


Inside the data service class, you can define the BehaviorSubject variable from string type to hold search text value.

Inside the constructor I have initialize it with empty string.

private searchText: BehaviorSubject<string>;

  constructor() {
    this.searchText = new BehaviorSubject<string>('');

   }
  
Then I am going to add getters and setters as below.


  public getUserName() {
    return this.userName.asObservable();
  }

  public changeUserName(newUserName) {
    this.userName.next(newUserName);
  

Now we have done with implementing shared data service class to handle behavioral subjects. Please see service code below.


import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})

export class DataService {

  private searchText: BehaviorSubject<string>;

  constructor() {
    this.searchText = new BehaviorSubject<string>('');
   }

   public getSearchText() {
    return this.searchText.asObservable();
  }

  public setSearchText(searchText) {
    this.searchText.next(searchText);
  }
}
  

Now I can subscribe to this getSearchText() method from my landing.component.ts where I want to print new search text.

I need to inject my service class to the landing.component.ts file through the constructor.

Before inject I have imported the data.service.ts in my landing.component.ts file.


import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { flower } from '../../domain/flower';
import {CardModule} from 'primeng/card';
import {CheckboxModule} from 'primeng/checkbox';
import { DataService } from 'src/app/services/data.service';

@Component({
  selector: 'app-landing',
  templateUrl: './landing.component.html',
  styleUrls: ['./landing.component.scss'],
  encapsulation: ViewEncapsulation.None
})

export class LandingComponent implements OnInit {

  myFlowerList:flower[]=[];
  selectedFlowers: string[] = [];
  checkedList:string[]=[];
  searchText:string='';
  constructor(private dataService:DataService) { }

  ngOnInit() {
    this.mySellingFlowers();
    this.dataService.getSearchText().subscribe(response => {
      this.printSearchtext(response);
    })
  }

  printSearchtext(searchText){
    this.searchText = searchText;
  }

  mySellingFlowers(){
    let rose = new flower();
    rose.name = "Rose";
    rose.price = 100;
    rose.availableQuantity = 1000;
    rose.isChecked = false;
    this. myFlowerList.push(rose);

    let lily = new flower();
    lily.name = "Lilly";
    lily.price = 80;
    lily.availableQuantity = 2000;
    lily.isChecked = false;
    this. myFlowerList.push(lily);

    let tulip = new flower();
    tulip.name = "Tulip";
    tulip.price = 100;
    tulip.availableQuantity = 2300;
    lily.isChecked = false;

    this. myFlowerList.push(tulip);

    let carnation = new flower();
    carnation.name = "Carnation";
    carnation.price = 50;
    carnation.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(carnation);

    let gerbera = new flower();
    gerbera.name = "Gerbera";
    gerbera.price = 50;
    gerbera.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(gerbera);

    let orchid = new flower();
    orchid.name = "Orchid";
    orchid.price = 50;
    orchid.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(orchid);

  }

  trackFlowers(index,flower){
    return flower?flower.name:undefined
  }
}
  

Once you subscribe to the behavior subject whenever it value change it will execute the printSearchtext() method.

Here I have print it in landing.component.html file as below.

<div>Your search text is: {{searchText}}</div>

When user type new search term we must update behavior subject.

I added below code in app.component.ts file to do that. Here also you need to inject your service class.

Then call setSearchText() method to update new values.

Here is the code in app.component.html. I have added input event where it triggers whenever user types something on the text filed.



  <header>
  <div class="container">
    <a href="" class="logo">My flower shop</a>
  <span [style]="{'padding-left':'10px'}" >
    
      <input type="text" pInputText placeholder="Search" (input)="updateSearchText()" [(ngModel)]="searchText" />
  </span>
    <nav>
      <ul>
        <li><a href="" routerLink="/">Landing</a></li>
        <li><a href="" routerLink="/home">Home</a></li>
      </ul>
    </nav>
  </div>
</header>

<div class="container">
  <router-outlet></router-outlet>
</div>

In app.component.ts I have defined the updateSearchText() method and call data service to update behavior subject.

Import the data.service and inject it through constructor. This is called Dependency Injection in Angular. I will explain it in detail future.


import { Component, ViewEncapsulation } from '@angular/core';
import {InputTextModule} from 'primeng/inputtext';
import { DataService } from './services/data.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  encapsulation: ViewEncapsulation.None

})
export class AppComponent {
  title = 'my-flower-store';
  searchText:string='';

  constructor(private dataService:DataService){

  }

  updateSearchText(){
    this.dataService.setSearchText(this.searchText);
  }
}
  

Now you can see the magic happens in your browser.

how you can share data between parent child components

Good Luck with learning concept of sharing data between unrelated components. Next chapter we will see how you can share data between parent child components.

Comments

Popular posts from this blog

The Power of ChatGPT and Whisper Models

A Deep Dive into Natural Language Processing Natural Language Processing (NLP) has seen a significant boost in recent years due to advancements in artificial intelligence and machine learning. Two models that have shown remarkable success in NLP are ChatGPT and Whisper. In this article, we will delve into the power of these models and their applications in the field of NLP. ChatGPT is a transformer-based language model developed by OpenAI that uses unsupervised learning to predict the next word in a sentence based on the context of previous words. ChatGPT is a generative model that is trained on large datasets of text, such as books and articles, and can be fine-tuned for specific tasks, such as question-answering or dialogue generation. ChatGPT is known for its ability to produce human-like text, making it an ideal tool for applications such as chatbots, content creation, and language translation. Whisper, on the other hand, is a paraphrasing model developed by Google that is based on

Angular PrimeNG checkboxes styling and events handling

  Getting Started With PrimeNG Styling in Angular App This chapter I am planning to show how you can handle events of the checkboxes. For that I will use checkbox for every card to place the order.  To use PrimeNG checkboxes you have to import checkbox module in app.module.ts file. import {CheckboxModule} from 'primeng/checkbox'; import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { LandingComponent } from './modules/landing/landing.component'; import { HomeComponent } from './modules/home/home.component'; import { CardModule } from 'primeng/card'; import {CheckboxModule} from 'primeng/checkbox'; @NgModule({ declarations: [ AppComponent, LandingComponent, HomeComponent ], imports: [ BrowserModule, AppRoutingModule, CardModu

Angular NgFor directive and trackby

Today we will learn about NgFor one of the core directive of angular. NgFor helps to build list and tables in Angular   Let us see the example in our flower store app. In the landing page I am going to print list of flowers that are available in the store. Later we will add images and show them in a carousel to rotate automatically. First we will create the domain class called flower.ts and you can copy paste below code.  export class flower{ constructor() { } name:string=''; price:number = 0; availableQuantity:number = 0 } To use this domain class inside another component you must specify export keyword along with the class keyword. Flower domain has 3 attributes to store name of the flower then price and the available quantity. Now we can create the array from the flower type as below inside the landing.component.ts file. myFlowerList:flower[]=[]; I will call a method inside ngOnInit to add values to the array as below. ngOnInit is one of t