Video at https://www.youtube.com/watch?v=ajosuyhcKV4
I need to inform the user when the application is loading data – and when it is not loading anymore. Usually,the data comes from a backend via an HTTP call– and will be some timeout before it becomes available. So – simple – just intercept this and then show some spinning to the user,right ?
I found the documentation about interceptors at https://angular.io/api/common/http/HttpInterceptor – and you can find more searching on google / bing .
Also,my inspiration was started from here:
https://grensesnittet.computas.com/loading-status-in-angular-done-right/
But,if we intercept,how to distribute ? The services singleton in Angular will provide help
import { Injectable } from '@angular/core';
import { Subject,Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoaderService {
constructor() {
this.s = new Subject<boolean>();
}
public s: Subject<boolean>;
public loading$(): Observable<boolean> {
return this.s.asObservable();
}
public isLoading(b: boolean) {
this.s.next(b);
}
}
So I have created the HttpInterceptor to call the service,like here:
import { Injectable } from '@angular/core';
import {
HttpEvent,HttpInterceptor,HttpHandler,HttpRequest,HttpErrorResponse
} from '@angular/common/http';
import { Observable,throwError } from 'rxjs';
import { catchError,tap,finalize } from 'rxjs/operators';
import { LoaderService } from './loader.service';
/** Pass untouched request through to the next request handler. */
@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private requests: HttpRequest<any>[] = [];
constructor(private ls: LoaderService ) {
}
removeRequest(req: HttpRequest<any>) {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.requests.splice(i,1);
}
this.ls.isLoading(this.requests.length > 0);
}
// https://grensesnittet.computas.com/loading-status-in-angular-done-right/
intercept(req: HttpRequest<any>,next: HttpHandler):
Observable<HttpEvent<any>> {
this.requests.push(req);
this.ls.isLoading(true);
return next.handle(req).pipe(
finalize(() => this.removeRequest(req))
);
}
}
And now it is simple to display in any page: – in the HTML
<mat-spinner *ngIf="isLoading"></mat-spinner>
and in the .ts pass in the constructor via DI
@Component({
selector: 'app-covid-navig',
templateUrl: './covid-navig.component.html',
styleUrls: ['./covid-navig.component.css']
})
export class CovidNavigComponent {
public isLoading = false;
constructor(private breakpointObserver: BreakpointObserver
,private err: ErrorService
,private snackBar: MatSnackBar
,private ls: LoaderService) {
this.err.NextError().pipe(
tap(it => {
this.snackBar.open(it,'ERROR',{
duration: 5000,
});
}),
shareReplay()
).subscribe();
this.ls.loading$().subscribe(it => this.isLoading = it);
}
Simple,right ?
Leave a Reply