Let's say I've a parent component, HomeComponent
, with multiple nested component, TeamsStandingComponent
.
TeamsStandingComponent
must show data collected from an API call, using a common but private store, TeamsStandingStore
.
Now I'll show you my code.
HomeComponent
:
import { Component } from '@angular/core';
@Component({
selector: 'home',
templateUrl: '../templates/home.html'
})
export class HomeComponent {
constructor(
) {}
}
And this is the HomeComponent
template:
<div class="top-three-standings__wrapper">
<teams-standing #standing1 [leagueId]="426"></teams-standing>
<teams-standing #standing2 [leagueId]="439"></teams-standing>
</div>
This is the TeamsStandingComponent
:
import { Component, AfterViewInit, NgZone, ChangeDetectorRef,
ElementRef, Input } from '@angular/core';
import { TeamsStandingStore } from '../stores/teams-standing';
import { HttpClient } from '../services/http-client'; // you can ignore this
@Component({
selector: 'teams-standing',
providers: [HttpClient], // you can ignore this
templateUrl: '../templates/teams-standing.html'
})
export class TeamsStandingComponent implements AfterViewInit {
@Input() private teams: Object;
@Input() private leagueId: string;
private teamsStandingStore: TeamsStandingStore;
constructor(
private TeamsStandingStore: TeamsStandingStore,
private ngzone: NgZone,
private cdref: ChangeDetectorRef
) {
console.clear();
this.teamsStandingStore = TeamsStandingStore;
}
public ngAfterViewInit () {
this.ngzone.runOutsideAngular( () => {
this.teamsStandingStore.standings
.subscribe( (data) => {
this.teams = data;
this.cdref.detectChanges();
} );
});
this.http.get(`competitions/` + this.leagueId + `/leagueTable`)
.subscribe(
(data: any) => this.teamsStandingStore.showStandings(data.json()),
(error) => console.log(error)
);
}
}
And this is the TeamsStandingComponent
template:
<div class="teams-standing__table">
<h2>{{leagueId}} - {{teams?._links?.competition?.href}}</h2>
<h3>{{teams?.leagueCaption}}</h3>
<div *ngFor="let team of teams?.standing">
{{team.teamName}}
{{team.crestURI}}
</div>
</div>
And finally this is the TeamStandingStore
:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Rx';
@Injectable()
export class TeamsStandingStore {
private standings: Subject<any> = new Subject<any>();
private showStands: Subject<any> = new Subject<any>();
constructor() {
this.showStands
.subscribe(this.standings);
}
public showStandings(standings) {
this.showStands.next(standings);
}
}
My issue is that those nested component, TeamsStandingComponent
, show the same data, even if every component calls a different endpoint - as you can see - and has a different response.
PS: I'm using @angular v.2.4.9 and rxjs v.5.0.2
I believe all the nested components are getting the same value because they are all using the same instance of the TeamStandingStore
.
You do not show your module where you are providing your TeamStandingStore
, but my guess your providing it as the module level. This means every component is getting the same instance of the Store and thus all subscribing to the same standings
observable.
What you may want to do in this case is provide the Store at the component level instead of at the module level so each TeamStandingComponent
has it's own instance. You would do this by providing the TeamStandingStore
in the component decorator like this:
@Component({
selector: 'teams-standing',
providers: [HttpClient, TeamStandingStore], // <- insert TeamStandingStore here
templateUrl: '../templates/teams-standing.html'
})
export class TeamsStandingComponent implements AfterViewInit {
@Input() private teams: Object;
@Input() private leagueId: string;
private teamsStandingStore: TeamsStandingStore;
constructor(
private TeamsStandingStore: TeamsStandingStore,
private ngzone: NgZone,
private cdref: ChangeDetectorRef
) {
console.clear();
this.teamsStandingStore = TeamsStandingStore;
}