I would like to make a loading When requesting data from ngrx+ api http request
I have a state that contain loading boolean, and another with raw data.
I set loading to false when data arrive.
the problem viewChild
don't find reference because data arrive before loading set to false.
I get error
ERROR TypeError: Cannot read property 'nativeElement' of undefined
Here's the template
<div *ngIf="isLoading; else kpi"><mat-spinner></mat-spinner></div>
<ng-template #kpi>
<div class="chartWrapper">
<div class="scrollArea">
<div class="chartAreaWrapper">
<canvas #lineChart id="lineChart" width="1200" height="400"></canvas>
</div>
</div>
<canvas #stickyAxis id="chartAxis" height="400" width="0"></canvas>
</div>
</ng-template>
in component
export class BranchKpisComponent implements OnChanges, OnInit, OnDestroy {
@ViewChild('lineChart', { static: true }) private chartRef;
I'm using ngrx store
I have the selectors
selectLoadings$ = this.store.pipe(select(selectLoadings));
selectedDataByBranch$ = this.store.pipe(
select(selectBranchDirections, {
branchId: this.branchId,
location: 'directionsByBranch',
dir: 0
})
inside ngOnchange()
I subscribe to loading and data observable ( separately )
this.selectLoadings$.subscribe(
loading => (this.isLoading = loading.directionsByBranch[this.branchId])
);
this.selectedDataByBranch$
.pipe(filter(data => Object.keys(data).length > 0))
.subscribe(selectedDataByBranch => {
this.trainsDatasets = this.getDatasets(selectedDataByBranch);
this.context = this.chartRef.nativeElement; ### Error undefined chartRef
Inside reducer when I get data I set loading to false
case ESchedulesActions.GetAllSchedulesByDirectionSuccess: {
return {
...state,
directionsByBranch: {
...state.directionsByBranch,
[action.payload[1]]: action.payload[0]
},
loadings: {
...state.loadings,
directionsByBranch: {
...state.loadings.directionsByBranch,
[action.payload[1]]: false
}
}
};
}
You could use [hidden] instead of *ngIf. It will still have the element you want to view in the DOM. Would need another one instead of the else which is the opposite.
<div [hidden]="!isLoading"><mat-spinner></mat-spinner></div>
<ng-template [hidden]="isLoading">
<div class="chartWrapper">
<div class="scrollArea">
<div class="chartAreaWrapper">
<canvas #lineChart id="lineChart" width="1200" height="400"></canvas>
</div>
</div>
<canvas #stickyAxis id="chartAxis" height="400" width="0"></canvas>
</div>
</ng-template>
In terms of performance there won't be much difference if at all due to the size of the code.