简体   繁体   中英

Angular 5- pass data between sibling components to use at the same time

I have an Angular app where I have two sibling components being rendered at the same time, and they need the same data. (One is a nav bar listing all the sites, and the other is in my router outlet that lists all the sites/graphs the data etc.)

In order to make fewer http requests want to make a call to the service one time, store the data in a global variable, then access that data from the sibling component.

But, since they're both loading at the same time, the data called from one component doesn't have time to make it into the service before the other component tries to receive it from the service.

Component A (storing the data in a global variable 'all_sites' in the service)

  ngOnInit() {
    this.myService.getSites()
    .subscribe(data => {
    this.sites = data
    this.myService.all_sites = data
  })
}

Component B Comes up undefined.

 ngOnInit() {
  console.log(this.myService.all_sites)
 }

So is there a way for me to send data to a sibling component and get them both to use the data at the same time? Like I'm doing this in the parent:

<app-componentA></app-componentA>
<app-componentB></app-componentB>

Other complications make it difficult to just call from the parent (Authtoken2 stuff). My ultimate goal is to lighten the load on the server

Thanks!! Any suggestions are appreciated

It seems you are using component A and component B in one component. So can you make that http call in that parent and use ngIf something like:

<div *ngIf="this.sites.length">
<app-componentA></app-componentA>
<app-componentB></app-componentB>
</div>

Hope it helps!

What you are doing IN component A ngOnInit(), you can actullay do it in the parent component ngOnInit() and pass this.sites as inputs to both of the siblings.

in that manner, you can achieve what you want. less requests and children will load once the parent is loaded and called the service

If you want to enforce this scenario :

Create a Subject which emits a value when the http response arrives. After that it is pretty simple, you can just subscribe to this Observable to get the data in your other component.

Send http request in parent component :

An other simple solution is to send the request the parent component and pass the value to the child components with Input .

Consider using redux :

Redux is a really powerful tool. You can store the response in state and Observers in child components will be notified with selectors.

您可以尝试使用Object.assign(this.myService.all_sites, data)代替this.myService.all_sites = data

The reason for the error is that both components call ngOnInit before returned observable from the service in the call made from componentA has been resolved. So in the call made by componentB the field all_sites is still undefined .

The easiest way to do this is to cache the observable and have all components still access the method. Only the service should know/care about caching.

export class MyService {
    private getSitesObservable: Observable<Sites[]>;
    getSites(): Observable<Sites[]> {
        if(!this.getSitesObservable)
            this.getSitesObservable = this.http.....;
        return this.getSitesObservable;
    }
}

And then in both components (or any component that calls this service's method):

ngOnInit() {
    this.myService.getSites().subscribe(data => {
        this.sites = data;
  });
}

You could move the service call logic into the parent component that houses both the components, and passing the data in as inputs:

so the structure would be as follows

<app-component-parent>
    <app-component-a></app-component-a>
    <app-component-b></app-component-b>
<app-component-parent>

In app-component-parent.component.ts, call the service on ngOnInit:

sites: SITES_TYPE;

ngOnInit() {
    this.myService.getSites()
    .subscribe(data => {
    this.sites = data
  })
}

Then in the siblings, pass 'sites' in as an input:

<app-component-a [sites]="sites"></app-component-a>
<app-component-b [sites]="sites"></app-component-b>

And in each of the components, do the following:

@Input()
sites: SITES_TYPE;

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