简体   繁体   中英

How to share data between sibling components in Angular

I am still learning and I got stuck so I need to ask a question. My understanding of Input Output decorators is that I need to add selector to html of parent to be able to use them, but for my case I don't think it's the way to go, but someone can prove me wrong.

CASE: For readability purposes I have split components. I have one component, data-fetch-transform that gets the data form local JSON file and does some adjustments to it, and another one, that wants to take that data for further use.

PROBLEM: I am unsure how to read the data from one component in the other. On the example below, how can I get countryNumber and centerNumber result in my other component. I intend to have data-fetch-transform.component.ts just manipulate the data and used in other components

Target component

project/src/app/data-use/data-use.component.ts

Data Source component

project/src/app/data-fetch-transform/data-fetch-transform.component.ts

    import { Component, OnInit } from '@angular/core';
    import * as data from '../../../../../data/Data.json';
    
    @Component({
      selector: 'app-datafetch-transform',
      templateUrl: './datafetch-transform.component.html',
      styleUrls: ['./datafetch-transform.component.css'],
    })
    export class DatafetchComponent implements OnInit {
      public dataList: any = (data as any).default;
      dataPointCount = this.data.length!!;
    
     uniqueValues = (dt: [], sv: string) => {
        var valueList: [] = [];
        for (let p = 0; p < this.dataPointCount; p++) {
          valueList.push(dt[p][sv]);
        }
    
        var uniqueValues = new Set(valueList);
        return uniqueValues.size;
      };
    
    countryNumber=this.uniqueValues(this.dataList, 'Country')
    centerNumber=this.uniqueValues(this.dataList, 'Center Name')
    constructor() {}

    ngOnInit(): void {}
    }

You don't need another component for data manipulation (data-fetch-transform), you need a service (data-fetch-transform-service) where you should do the logic.

HERE IS WHAT YOU SHOULD HAVE IN THE SERVICE

 private _dataList = new behaviorSubject([]);
 public dataList$ = _dataList.asObservable();
    
        for (let p = 0; p < this.dataPointCount; p++) {
          // ... do your thing 
          _valueList.next(result);
        }
   

and in the component you just subscribe to the service: declarations:

private _subscription = new Subscription()

in constructor:

private dataService:DataFetchTransformService

and in ngOnInit:

this_subscription.add(this.dataService.dataList$.subscribe((response:any)=>{
this.data = response;
}))

in ngOnDestroy():

ngOnDestroy(){
this._subscription.unsubscribe();
}

I strongly suggest to stop using any since it can bring a lot of bugs up. Also, as a good pattern, I always suggest use behaviorSubject only in the service as a private variable and user a public observable for data.

WHY IS BETTER TO USE A SERVICE You can subscribe from 100 components and writing only 4 lines of code you bring the data anywhere. DON'T FORGET TO UNSUBSRIBE IN ngOnDestroy If you don't unsubscribe, you'll get unexpected behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM