2016-07-01 15 views
9

Was ich versuche zu tun ist:
Ich möchte den Spinner immer dann verwenden, wenn eine HTTP-Anfrage zutrifft. Mit anderen Worten möchte ich, dass Benutzer einen Ladebildschirm sehen, wenn eine http-Anfrage in meiner app.component passiert.
Meine Spinner.component und Spinner-Service-Dateien sind identisch mit der Antwort in this Frage.
Und Komponente meine app.component derAngular 2 Loader auf jeder HTTP-Anfrage

ist
@Component({ 
    selector: 'todoApi', 
    template: ` 
     <div class="foo"> 
      <spinner-component></spinner-component> 
      <h1>Internship Project</h1> 
      <a [routerLink]="['Dashboard']">Dashboard</a> 
      <a [routerLink]="['Tasks']">List</a> 
      <router-outlet></router-outlet> 
     <div> 
    `, 
    directives: [ROUTER_DIRECTIVES,SpinnerComponent], 
    providers: [ 
     ROUTER_PROVIDERS, 
    ] 
}) 

@RouteConfig([ 
    { 
     path: '/dashboard', 
     name: 'Dashboard', 
     component: DashboardComponent, 
     useAsDefault: true 
    },{ 
     path: '/tasks', 
     name: 'Tasks', 
     component: TaskComponent 
    },{ 
     path: '/detail/:id', 
     name: 'TaskDetail', 
     component: TaskDetailComponent 
    }, 
]) 

Um conclue, wann immer eine HTTP-Anfrage in einer dieser Routen stattfindet, möchte ich den Spinner an Benutzer zeigen. Ich weiß, dass dies eine schlechte Frage war, aber ich bin neu bei eckigen 2 und ich wäre wirklich dankbar, wenn mir jemand dabei helfen könnte.
Vielen Dank!
bearbeiten !:
Lösung mit Günther Antwort: wickelte ich meine http und spinner-service in eine HttpClient Komponente und verwendet es anstelle der normalen http-Modul. Hier ist meine HttpClient Komponente:

import { Injectable } from '@angular/core'; 
import { Http, Headers } from '@angular/http'; 
import { SpinnerService} from './spinner-service'; 

@Injectable() 
export class HttpClient { 
    constructor(
     private http: Http, 
     public spinner: SpinnerService 
    ){ 

    } 

    createAuthorizationHeader(headers:Headers) { 
    headers.append('Authorization', 'Basic ' + btoa('username:password')); 
    } 

    get(url) { 
    this.spinner.start(); 
    let headers = new Headers(); 
    this.createAuthorizationHeader(headers); 
    return this.http.get(url, { headers: headers }).do(data=> {this.spinner.stop()}); 
    } 

    post(url, data) { 
    this.spinner.start(); 
    let headers = new Headers(); 
    this.createAuthorizationHeader(headers); 
    return this.http.post(url, data, { headers: headers }).do(data=> {this.spinner.stop()}); 
    } 
} 
+0

Vielleicht erstellen Sie individueller Service HTTP-Anfragen zur Verlängerung des HttpClass durch die Winkel und verfolgen den 'isBusy' Zustand in Ihrem benutzerdefinierten Dienst auszuführen auf jede Anfrage. – Lekhnath

Antwort

6

einen Dienst verwenden, die zwischen Http (es gibt Antworten bereits, wie etwa Einwickeln Http in Ihrer eigenen Klasse) und die <spinner-component> geteilt wird. Siehe auch https://angular.io/docs/ts/latest/cookbook/component-communication.html

Im Shared Service halten einen Zähler von gestartet (Erhöhung) und abgeschlossen/nicht bestanden HTTP-Anforderungen und informiert jedes Mal der <spinner-component>, wenn die Zähler Änderungen 0->0 oder >0-0 selbst zu aktivieren oder deaktivieren .

+0

Das war eine sehr nützliche Antwort für mich Günter! Danke vielmals! Ich werde mein Bestes versuchen und sehen, ob Wrapping Http das Problem lösen wird oder nicht. – ozata

+0

Nochmals vielen Dank Günter! – ozata

+0

Bitte können Sie ein Beispiel erstellen? – gtzinos

1

Gerade für die Menschen, die hier werden von jetzt an ...

Mit dieser Lösung der Spinner werden nicht mit der HTTP-Anforderung im Fall eines Fehlers zu stoppen. Achten Sie darauf, folgende Sie tun das:

... 
return this.http.post(url, data, { headers: headers }) 
    .do(data=> {this.spinner.stop()}, 
    err=> {this.spinner.stop()); 
... 
3

Vielen Dank für Ihre Antwort Günter Zöchbauer ist, ein Beispiel, das ich auf Grund meiner Bedürfnisse gebaut. Ich habe keinen HTTP-Wrapper verwendet, der einfacher zu verwenden wäre. Dieses Beispiel funktioniert jedoch mit mehreren Serviceaufrufen, die auf Ihrem Gegenvorschlag basieren. Hoffe es hilft jemandem :)

  1. Erstellen Sie den Loader-Service.

    import { Injectable } from '@angular/core'; 
    import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 
    
    @Injectable() 
    
    export class LoaderService { 
        public loaderCounter: BehaviorSubject<number> = new BehaviorSubject<number>(0); 
        displayLoader(value: boolean) { 
         let counter = value ? this.loaderCounter.value + 1 : this.loaderCounter.value - 1; 
         this.loaderCounter.next(counter); 
        } 
    } 
    
  2. Fügen Sie den Dienst innerhalb des Anbieters Ihrer maain Moduldatei (Ex: AppModule)

  3. In Ihrer Hauptkomponentendatei (Ex: AppComponent), auf die Änderungen abonniert und die spiegelt Loader (in meinem Fall ist es eine separate Komponente).

    //Imports 
    import { Subscription } from 'rxjs/Subscription'; 
    import { LoaderService } from './core/loader.service'; 
    .. 
    @Component({ 
        selector: 'my-app', 
        template: ` 
        <div class="container-fluid content"> 
         <router-outlet></router-outlet> 
        </div> 
        <spinner [visible]="displayLoader"></spinner> 
        ` 
    }) 
    
    export class AppComponent implements OnInit, OnDestroy { 
        displayLoader: boolean; 
        loaderSubscription: Subscription; 
        constructor(private loaderService: LoaderService) {} 
    
        ngOnInit() { 
         this.loaderSubscription = this.loaderService.loaderCounter.subscribe((counter: number) => { 
          this.displayLoader = counter != 0; 
         }); 
        } 
    
        ngOnDestroy() { 
         this.loaderSubscription.unsubscribe(); 
        } 
    } 
    
  4. Mit dem Loader Service:

    import { LoaderService } from './core/loader.service'; 
        .. 
        export class SampleComponent implements OnInit { 
         constructor(private _service: SomeService, private loader: LoaderService) { } 
    
        ngOnInit() { 
         this.loader.displayLoader(true); 
         this._service.getBalance().subscribe(
          response => ..do something.., 
          () => .. error.., 
          () => this.loader.displayLoader(false) 
         ); 
        } 
    } 
    
+0

Sehr cool ... aber warum ist Ihr Ajax innerhalb der Komponente anrufen? Ich denke, Sie sollten die Loader-Service-Methode innerhalb eines anderen Dienstes aufrufen, wo der Ajax-Anruf gemacht wird, nicht? – MadCatm2

+0

Aus meinen Kenntnissen von Angular 2 haben Sie einen Service, und Sie rufen einfach auf Komponentenebene die Werte auf, die Sie haben. Ich bin mir nicht ganz sicher, warum Sie mehrere Dienste benötigen, da Sie die Antwort immer noch mit dem Modell/den Variablen innerhalb der Komponente verbinden müssen. –