Reputation: 3774
I have 2 components and a service. BehaviorSubject in the service class has default values and also it pulls in data from an API. The first component gets the latest data which is pulled from the API, but the second component only displays the default values. What could be wrong in my code. Plz advise!
export class WebService {
public btnsOnResponse; //activates buttons when server responds positive
BASE_URL = 'http://localhost:3000/api';
private stats = new BehaviorSubject<IStats>({
date: this.datePipe.transform(new Date(), 'dd-MM-yyyy'),
answeringMachine:0,
hangUp:0,
conversations:0
});
public stats$ = this.stats.asObservable();
constructor(private http: HttpClient) {
this.getStatsbyDate('04-03-2018');
}
Components: 1st Component
export class StatsComponent {
public stats: IStats;
constructor(private webService: WebService, private datePipe: DatePipe) {
this.webService.stats$.subscribe((data) => {
if (data !== null) { this.stats = data; }
// else { this.webService.stats.next(this.stats); }
console.log(data);
})
}
export class ChartsComponent {
private stats: IStats;
constructor(private webService: WebService) {
this.webService.stats$.subscribe((data: IStats) => {
this.stats = data;
})
console.log(this.stats);
}
Upvotes: 1
Views: 143
Reputation: 11000
That happens because you run another async
operation, as you wrote in your comment - this.http.get<IStats>
. That async function has a callback - subscribe()
with functions in it. Because it is async
and JavaScript is single-threated, Angular continues building your application (components etc.) while that callback is being placed in so called "Callback Queue". It fires only after Call stack (normal Javascript functions) is empty - so when Angular finishes building your app (in general). So that means that this.stats.next(data)
is being fired after you subscribe your BehaviourSubject, so you get one initial value and later comes another.
You can remove that async
and next
other object:
constructor(private http: HttpClient) {
// this.getStatsbyDate('04-03-2018');
this.stats.next({
date: this.datePipe.transform(new Date(), 'dd-MM-yyyy'),
answeringMachine:100,
hangUp:100,
conversations:100
});)
}
You should get only the last value.
Upvotes: 1
Reputation: 3737
The problem that you're having is that you are defining a BehaviorSubject and the initial values that are sent through the Observables pipeline, but you are not actually pushing the next set of values through that pipeline whenever you receive the data back from the API (more reading from RxJS). Here is your updated code example:
export class WebService {
public btnsOnResponse; //activates buttons when server responds positive
BASE_URL = 'http://localhost:3000/api';
private stats = new BehaviorSubject<IStats>({
date: this.datePipe.transform(new Date(), 'dd-MM-yyyy'),
answeringMachine:0,
hangUp:0,
conversations:0
});
public stats$ = this.stats.asObservable();
constructor(private http: HttpClient) {
// I am going to assume that the this.getStatsByDate() returns an Observable of some kind.
this.getStatsbyDate('04-03-2018')
.subscribe(
// You needed to subscribe to this function call and then call the .onNext() function in order to pass in the next set of data to your this.stats$ Observable.
(val: any) => this.stats$.onNext(val)
);
}
// I am guessing that you have an implementation of the this.getStatsByDate() function somewhere here, since you didn't include it in your original post.
}
Upvotes: 0