I have a Donut chart that is loaded with data that is returned from three API calls. I have called the chart load, and API calls function in ngOninit(). But my chart does not load. I understand that in Angular, execution does not wait for API call to return data and that it continues to execute the rest of the program. Is there some way to wait till the API call returns the data and then load the chart?
TS
ngOnit(){
this.refreshDoneCount_DE();
this.refreshNotDoneCount_DE();
this.refreshPendingCount_DE();
this.refreshChart();
}
refreshDoneCount_DE(){
this.dashboard.get_done_count_de_api().subscribe(data=>{
this.done_count_de=data;
});
}
refreshNotDoneCount_DE(){
this.dashboard.get_notdone_count_de_api().subscribe(data=>{
this.not_done_count_de=data;
});
}
refreshPendingCount_DE(){
this.dashboard.get_pending_count_de_api().subscribe(data=>{
this.pending_count_de=data;
});
}
Thank you
CodePudding user response:
I think you should to "surrender" to the async nature of HTTP requests instead of waiting for responses.
in a standard async handling pattern, instead of waiting you subscribe to the response.
Service
fetchData () {
return http.get('your-api-url');
}
component:
ngOnInit() {
this.yourService.fetchData().subscribe(data => {
// your code to handle the chart goes here
// this is only called when fetchData responds, so no need to write code to wait.
});
}
CodePudding user response:
I had faced a similar situation in the past, so I designed the chart in the following lines,
- Put a spinner in the page until API returns the data,
- Ensure you assign the received values and change the object reference otherwise your chart re-render will not trigger,
something like below,
ngOnInit() {
this.yourService.someMethod().subscribe(value => {
this.someInstanceVariable = value; //Initially make it undefined, once data arrived assign the value
this.chartData.series = value.data;
this.chartData = {...this.chartData};
}
)
}
When you execute this line this.chartData = {...this.chartData};
it will help your chart rerender after data arrival.
In the HTML make it like this,
<div *ngIf="!someInstanceVariable">
<chart-lib ...></chart-lib>
</div>
<div *ngIf="someInstanceVariable">
<div><!--spinner logic --></div>
</div>
EDIT 1:
Based on edit, I assume that user needs to be notified when all these observables complete,
forkJoin(
this.dashboard.get_done_count_de_api(),
this.dashboard.get_notdone_count_de_api(),
this.dashboard.get_pending_count_de_api()
).subscribe(
combinedValue=>{
//combinedValue will be an array of values received from all three apis in the order they appear inside the forkJoin() function
}
);