billy_56
billy_56

Reputation: 679

How can I show & hide simple CSS spinner while fetching data from database with my service - Angular 2>

In my application when I click on a button I would like to display a spinner.

I get a simple CSS spinner from this url : https://projects.lukehaas.me/css-loaders/

I added css to my main.css file, and after that I've added this line of code in my app.component.html :

<div class="loader">Loading...</div>

The reason why I choosed app.component.html is that I would like to make this spinner available everywhere in my application..

But for now on button click I'm getting list of persons from database. And this is how it looks (my component):

export class PersonComponent implements OnInit {

  private modalId: string;
  private persons: Array<Person>;

  constructor(private personsService: PersonsService) {}

  ngOnInit() {}

  // Here I'm getting data from database and I would like to display spinner/loader until all of data is loaded
  show() {
    $('#' + this.modalId).modal('show');
    this.personsService.getAll().do(data=>console.log(data)).subscribe(persons => this.persons = persons);
  }
}

Here is my app.component.html

<router-outlet></router-outlet>

<div class="loader">Loading...</div>

And here is my PersonsService.ts which is responsible for fetching data from database:

@Injectable()
export class PersonsService {

  public showSpinner: boolean = false;

  constructor(private _http: HttpClient) { }

  getAll(): Observable<Person[]> {
    this.showSpinner(); //Cannot invoke expression whose type lacks a call signature. -> I got this error here
    return this._http.get<Person[]>(apiUrl)
      .catch(
      (error: HttpErrorResponse) => {
          return Observable.throw(error);
      });
  // Somewhere here I would hide a spinner? Is this possible, I mean will this be shown when data is fully loaded or ?
  }


  displaySpinner() {
    this.showSpinner = true;
  }

  hideSpinner() {
    this.showSpinner = false;
  }

I need some if condition probably in my app.component.html so it might looks like this? :

<div *ngIf="personsService.showSpinner" class="loader">
    Loading...
</div>

Or I need to do something like this? :

<div *ngIf="personsService.showSpinner">
    <div class="loader">Loading...</div>
</div>

However this is not working now and I don't know how to achieve this, to simply show spinner when service is getting data from database, and to hide it when all of the data is fetched..

Thanks guys

Cheers

Upvotes: 0

Views: 824

Answers (2)

cyberpirate92
cyberpirate92

Reputation: 3166

Modify your service to use a BehaviorSubject instead of a plain boolean and take advantage of the rxjs pipe and tap operator so that you can set the spinner flag in the service itself, instead of toggling in every service consumer component.

@Injectable()
export class PersonsService {

  public showSpinner: BehaviorSubject<boolean> = new BehaviorSubject(false);
  public readonly apiUrl = "https://api.github.com/users";

  constructor(private _http: HttpClient) { }

  getAll(): Observable<Person[]> {
    this.showSpinner.next(true);
    return this._http.get<Person[]>(this.apiUrl).pipe(
      tap(response => this.showSpinner.next(false), 
      (error: any) => this.showSpinner.next(false))
    );
  }
}

You can use the async pipe to access showSpinner

<div class="loader" *ngIf="_personService.showSpinner | async">
</div>
<div *ngIf="!(_personService.showSpinner | async)">
  <button (click)="foo()">Click here</button>
  <pre>
    {{response | json}}
  </pre>
</div>

Demo

Upvotes: 0

Chellappan வ
Chellappan வ

Reputation: 27303

You can show hide and know the data base loading success and reading Full response using angular observe option

getAll(): Observable<HttpResponse<Person[]> {
        return this._http.get<Person[]>(apiUrl,{ observe: 'events' })
          .catch(
          (error: HttpErrorResponse) => {
              return Observable.throw(error);
          });
      // Somewhere here I would hide a spinner? Is this possible, I mean will this be shown when data is fully loaded or ?
      }

You can set the spinner on service or you can change the status of spinner inside components where you subscribe the getAll() observable example

components.ts

this.service.getAll().subscribe((response:HttpEvent<Object>)=>{
  //console.log(response);
  //import the HttpEventType from @angular/common/http
  if(response.type==HttpEventType.DownloadProgress){
    this.showSpinner = true;
  }
  if(response.type==HttpEventType.Response){
  this.showSpinner = true;
  }
})

Upvotes: 1

Related Questions