You users don't like when there is no indication from the application about what is happening. For example when you are loading data from the API and user has no clue about what is happening. I like displaying a small loading icon somewhere at the top to keep the aware about the application state.
To display a small loading indicator at the top of the screen for all API calls untill they return back we can write a small service, an interceptor and a component. I like something like the following
Following is a very simple interceptor
To display a small loading indicator at the top of the screen for all API calls untill they return back we can write a small service, an interceptor and a component. I like something like the following
Following is a very simple interceptor
Following is extremely simple service which just keep the state of loading indicator as true or false.import {Injectable} from '@angular/core'; import {HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'; import {Observable} from 'rxjs'; import {tap} from 'rxjs/operators'; import {LoadingService} from './loading.service'; @Injectable() export class LoadingInterceptor implements HttpInterceptor { constructor(private loadingService: LoadingService) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request).pipe( tap(res => { if (res.type === HttpEventType.Sent) { this.loadingService.loading$.next(true); } if (res.type === HttpEventType.Response) { this.loadingService.loading$.next(false); } }) ); } }
And now a simple component that displays a loading sign at the top-center of the screen.import {Injectable} from '@angular/core'; import {BehaviorSubject} from 'rxjs'; @Injectable({ providedIn: 'root'}) export class LoadingService { public loading$ = new BehaviorSubject(false); constructor() { } }
And finally the css of the component.import {Component, OnInit} from '@angular/core'; import {LoadingService} from '../services/loading.service'; @Component({ selector: 'amg-loading', styleUrls: ['loading.component.scss'], template: `<div *ngIf="loading$ | async" class="loader"> <div class="spinner"> Loading <div class="bounce1"></div> <div class="bounce2"></div> <div class="bounce3"></div> </div> </div>`}) export class LoadingComponent implements OnInit { public loading$; constructor(private loadingService: LoadingService) { this.loading$ = this.loadingService.loading$; } ngOnInit() { } }
.loader { z-index: 1000; position: absolute; top: 0; width: 120px; margin-left: 50%; margin-right: 50%; background-color: #ff0f3b; color: white} .spinner { text-align: center; } .spinner > div { width: 12px; height: 12px; background-color: #333; border-radius: 100%; display: inline-block; -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both; animation: sk-bouncedelay 1.4s infinite ease-in-out both; } .spinner .bounce1 { -webkit-animation-delay: -0.32s; animation-delay: -0.32s; } .spinner .bounce2 { -webkit-animation-delay: -0.16s; animation-delay: -0.16s; } @-webkit-keyframes sk-bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0) } 40% { -webkit-transform: scale(1.0) } } @keyframes sk-bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0); transform: scale(0); } 40% { -webkit-transform: scale(1.0); transform: scale(1.0); } }
Comments
Post a Comment