1

The project have a service.ts to make ajax call(http.post) and several components(abc.component.ts, bcd.component.ts etc) gets the data from the server through service.ts

I am using <div class="spinner"></div> for the spinner view. But, need a better approach to show loader either gif etc.

I want to show a spinner till the time each component fetch data from the server. How to do that?

service.ts

 getdata(){
      let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        let url = "http://883.82./Ser/soSe"; 
        return this.http.post(url, clientJson).map((res: Response) => res.json());
    }

abc.component.ts

let clientJson = {
        "aoId": "M_AO_918",
        "viewBys": ["usstate"],
        /* ... */
    };
  this.DataService.getdata(clientJson).subscribe(
        success => this.abcChart(success),
        error => this.errorMessage = error
    );
abcChart(jsonData) {
    /* ... */
}

bcd-chart.component.ts

 initData() {
        let clientJson = {
            "aoId": "M_AO_918",
            "viewBys": ["brands"], 
            /* ... */ 
        };
        this.DataService.getdata(clientJson).subscribe(
            success => this.bcdChart(success),
            error => this.errorMessage = error
        );
    }
    bcdChart(jsonData) {
        /* ... */
    }

styles.css

.spinner {
  width: 40px;
  height: 40px;
  background-color: #333;

  margin: 100px auto;
  -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
  animation: sk-rotateplane 1.2s infinite ease-in-out;
}

@-webkit-keyframes sk-rotateplane {
  0% { -webkit-transform: perspective(120px) }
  50% { -webkit-transform: perspective(120px) rotateY(180deg) }
  100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) }
}

@keyframes sk-rotateplane {
  0% { 
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) 
  } 50% { 
    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) 
  } 100% { 
    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
    -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
  }
}
.loading{
  background-color: #d35400;
}
  • I am using
    for the spinner view. But, need a better approach to show loader either gif etc.
    –  Jul 06 '17 at 05:07

3 Answers3

2

In your main html file where you keep <router-outlet></router-outlet> you need to keep the html of spinner so you can show it in any component throughout your angular app :

You also need to import service in the app.component.ts:

app.component.ts:

constructor(
  public serviceName: ServiceName
  ...
)

app.component.html:

<router-outlet></router-outlet>
<div *ngIf="serviceName.showSpinner" class="spiner">
    <!-- svg or gif of spinner  -->
</div>

In your service.ts:

public showSpinner: boolean = false;

getdata() {
    // show spinner when we start making request

    this.showLoadingSpinner();
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    let url = "http://883.82./Ser/soSe"; 
    return this.http.post(url, clientJson,clientJson1).map((res: Response) => {
      // response received so hide spinner now
      this.hideLoadingSpinner();
      return res.json();
    });
}

showLoadingSpinner() {
    this.showSpinner = true;
}

hideLoadingSpinner() {
    this.showSpinner = false;
}
Dhyey
  • 4,275
  • 3
  • 26
  • 33
  • `document.getElementById` in Angular ? Should never use dom manipulation in Angular, atleast for these trivial things. – Vamshi Jul 06 '17 at 05:17
  • @Skeptor u r right. I had incorrectly assumed that `abc` and `bcd` might not have a common parent, but i forgot about the ``, i have edited my answer. Thanks for pointing out. – Dhyey Jul 06 '17 at 05:26
  • No matter what the case , You should never do direct dom manipulations in Angular :) – Vamshi Jul 06 '17 at 05:34
  • I am using vanilla JS on the client side. How do I show animation until data is received from the server in my case? – vighnesh153 Apr 26 '19 at 15:54
0

Just have a boolean to track if the call is in progress or not

public inprogress = false;

set it to true before the http call and set it to false after the response is received

initData() {
    this.inprogress = true;
    this.DataService.getdata(clientJson).subscribe(
        success => this.bcdChart(success),
        error => this.errorMessage = error
    );
}
bcdChart(jsonData) {
    this.inprogress= false;
    /* ... */
}

If you like it keep it simple and handle in both error and success and not pollute bcdChart method you can do this way.

this.DataService.getdata(clientJson)
    .do(res => this.inprogress=false) 
    .subscribe(
        success => this.bcdChart(success),
        error => this.errorMessage = error
    );
Vamshi
  • 9,194
  • 4
  • 38
  • 54
0
  1. Create a function called show spinner

    get(url: string, options?: RequestOptionsArgs): Observable { this.showLoader();

        //return super.get ....
    

    }

2.after success hide loader

private showLoader(): void {

            this.loaderService.show();
}
 private hideLoader(): void {
            this.loaderService.hide();
}

3.Add Loader component

    import { Component, OnInit, OnDestroy } from '@angular/core';
    import { Subscription } from 'rxjs/Subscription';
    import { LoaderService } from './loader.service';
    import { LoaderState } from './loader';
    @Component({
        selector: 'angular-loader',
        templateUrl: 'loader.component.html',
        styleUrls: ['loader.component.css']
    })
    export class LoaderComponent implements OnInit {
    show = false;
    private subscription: Subscription;
    constructor(private loaderService: LoaderService) { }
    ngOnInit() { 

            this.subscription = this.loaderService.loaderState
                .subscribe((state: LoaderState) => {
                    this.show = state.show;
                });
    }
    ngOnDestroy() {
         this.subscription.unsubscribe();
    }

    }
  1. Loader component view

  2. Loader Service

    import { Injectable } from '@angular/core';
    import { Subject } from 'rxjs/Subject';
    import { LoaderState } from './loader';
    @Injectable()
    export class LoaderService {
    private loaderSubject = new Subject<LoaderState>();
    loaderState = this.loaderSubject.asObservable();
    constructor() { }
    show() {
            this.loaderSubject.next(<LoaderState>{show: true});
        }
    hide() {
            this.loaderSubject.next(<LoaderState>{show: false});
        }
    }
    
Rahul Cv
  • 725
  • 5
  • 12