web-dev-qa-db-fra.com

Comment afficher le spinner pour chaque requête HTTP dans angular 5?

je suis nouveau sur angular 5. Comment coder une fonction commune pour afficher le spinner pour chaque requête HTTP en angular 5.Veuillez m'aider à l'implémenter).

7
Harish

Vous pouvez utiliser Angular HttpInterceptor pour afficher un spinner pour toutes vos demandes, voici un bon article moyen sur la façon de mettre en œuvre un intercepteur http

De plus, vous devrez créer un service/module spinner et l'injecter dans votre intercepteur http. Enfin, dans votre méthode d'interception, vous pouvez utiliser la méthode finally rxJs pour arrêter votre spinner. Voici une implémentation simple:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.spinnerService.start();
    return next.handle(req).finally(res => this.spinnerService.stop() );
}

Prendre plaisir!

Bonus: voici un exemple d'implémentation du service spinner

14
Mehdi Benmoha

Cela n'a rien à voir avec les requêtes HttpClient ou HTTP. Il s'agit de savoir comment gérer les appels asynchrones en général (HTTP ou non).

Tu aurais dû

<div class="spinner" *ngIf="loading"; else showWhenLoaded"><div>
<ng-template #showWhenLoaded>
    <div>Your Content</div>
</ng-template>

et dans le fichier ts:

loading: boolean = true;

methodToTriggerRequest() {
    this.loading = true;
    this.http.get(...).subscribe(response => {
        if (resposnseNotAnError(response)) {this.loading = false}
    })
}
2
Phil

Le guide complet est ici avec un matériau mat-progress-spinner utilisation. Très cool!

1
trueboroda

Source Lien

Créer un service

//loader.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoaderService {

  public isLoading = new BehaviorSubject(false);
  constructor() { }
}

Créer un intercepteur de chargeur

    // loader.interceptors.ts
    import { Injectable } from '@angular/core';
    import {
        HttpErrorResponse,
        HttpResponse,
        HttpRequest,
        HttpHandler,
        HttpEvent,
        HttpInterceptor
    } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { LoaderService } from './loader.service';

    @Injectable()
    export class LoaderInterceptor implements HttpInterceptor {
        private requests: HttpRequest<any>[] = [];

        constructor(private loaderService: LoaderService) { }

        removeRequest(req: HttpRequest<any>) {
            const i = this.requests.indexOf(req);
            if (i >= 0) {
                this.requests.splice(i, 1);
            }
            this.loaderService.isLoading.next(this.requests.length > 0);
        }

        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

            this.requests.Push(req);
            console.log("No of requests--->" + this.requests.length);
            this.loaderService.isLoading.next(true);
            return Observable.create(observer => {
                const subscription = next.handle(req)
                    .subscribe(
                        event => {
                            if (event instanceof HttpResponse) {
                                this.removeRequest(req);
                                observer.next(event);
                            }
                        },
                        err => {
                            alert('error returned');
                            this.removeRequest(req);
                            observer.error(err);
                        },
                        () => {
                            this.removeRequest(req);
                            observer.complete();
                        });
                // remove request from queue when cancelled
                return () => {
                    this.removeRequest(req);
                    subscription.unsubscribe();
                };
            });
        }
    }

Maintenant, créez un composant de chargeur, puis ajoutez le composant d'application

  //loader.interceptor.ts
  import { Component, OnInit } from '@angular/core';
  import { LoaderService } from '../loader.service';

  @Component({
    selector: 'app-loading',
    templateUrl: './loading.component.html',
    styleUrls: ['./loading.component.css']
  })
  export class LoaderComponent implements OnInit {

    loading: boolean;
    constructor(private loaderService: LoaderService) {
      this.loaderService.isLoading.subscribe((v) => {
        console.log(v);
        this.loading = v;
      });
    }
    ngOnInit() {
    }

  }
1
Code Spy

Vous pouvez créer un service, puis y publier des événements au niveau racine de l'application qui y est abonnée. Laisse-moi expliquer.

broadcast.service.ts (c'est votre service)

import { Injectable } from '@angular/core';

import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';

import 'rxjs/add/operator/filter'
import 'rxjs/add/operator/map'

/**
 * This class acting as event service bus for the entire app.
 * No Need to register the class as this registered in the root level.
 * Can just inject to componets.
 */
@Injectable()
export class BroadcastService {

    private _handler: Subject<Message> = new Subject<Message>();

    broadcast(type: string, payload: any = null) {
        this._handler.next({ type, payload });
    }

    subscribe(type: string, callback: (payload: any) => void): Subscription {
        return this._handler
            .filter(message => message.type === type)
            .map(message => message.payload)
            .subscribe(callback);
    }
}

interface Message {
    type: string;
    payload: any;
}

Ensuite, vous pouvez publier et vous abonner à des événements comme celui-ci:

votre niveau de service:

this.broadcastService.broadcast('PROGRESS_START');

Au niveau du composant de votre application:

this.broadcastService.subscribe('PROGRESS_START', ()=>{
  //hit when you start http call
  this.myLoader = true;
});

enfin dans app.component.html:

<div *ngIf="myLoader">
 <!--YOUR LOADER SHOULD GO HERE-->
</div>
<router-outlet></router-outlet>

Il s'agit d'un moyen très générique à couplage lâche d'implémenter le chargeur de votre choix.

0
Rukshan Dangalla