Currently, I am integrating Angular Material into my Angular 11 project. One of the pages includes a mat-autocomplete component where I want to display a loading spinner while waiting for a request. Here is the code snippet I am using:
component.ts
this.searchServiceProviderCtrl.valueChanges
.pipe(
debounceTime(500),
tap(() => {
this.loading = true;
}),
switchMap((value) => this.serviceProviderAutocompleteService.searchByQuery(value)
)
)
.subscribe((response) => {
this.serviceProviders = response;
if (isNullOrUndefined(this.serviceProviders) || this.serviceProviders.length === 0) {
this.emptyServiceProviders = true;
this.loading = false;
}
});
component.html
<mat-form-field>
<input matInput placeholder="Search" aria-label="State" [matAutocomplete]="auto" [formControl]="searchServiceProviderCtrl">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngIf="loading" class="is-loading">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</mat-option>
<mat-option *ngIf="emptyServiceProviders">No results</mat-option>
<ng-container *ngIf="!loading">
<mat-option *ngFor="let serviceProvider of serviceProviders" [value]="serviceProvider">
<span><b>{{serviceProvider.lastName + ' ' + serviceProvider.firstName}}</b></span>
</mat-option>
</ng-container>
</mat-autocomplete>
</mat-form-field>
Initially, I did not see the loader, and upon investigation, I realized that my service was synchronous. To simulate a delay, I added a portion of non-functional code with a sleep(5000ms) effect:
searchByQuery(query: string): Observable<any[]> {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < 5000);
return of(this.values.filter((v) => v.firstName.toLowerCase().indexOf(query.toLowerCase()) > -1 || v.lastName.toLowerCase().indexOf(query.toLowerCase()) > -1));
}
Even with this workaround, I still did not see the loading spinner. To debug, I added {{loading}} in the HTML, and it never changed to true despite the tap() => this.loading = true being called. Can anyone suggest why the loading boolean is not updating in the HTML?