'how to show loading animation before element is shown in angular

i am fetching some data via a angular service and takes about 2-3s to appear . so the HTML elements corresponding to that service also takes time to load . is there any way to show loading animation for that particular elements?



Solution 1:[1]

you can use the finalize operator from RxJs https://www.learnrxjs.io/learn-rxjs/operators/utility/finalize

getData() {
  this.showLoader = true;
  this.service.getYourObs().pipe(finalize(() => this.showLoader = false)).subscribe(...);
}

Solution 2:[2]

You need to track a loading state and have the template react accordingly.

If you're not using something like @ngrx/store for example, have a variable in your component.

isLoading = false

When fetching data, change that variable...

getSomeData(){
  this.isLoading = true;
  
  this.service.getSomeData().subscribe((data) => {
    //... Do stuff with data
    this.isLoading = false;
  })
}

...then in your template...

<ng-container *ngIf="!isLoading; else loader">
  <!-- Visible if not loading -->
</ng-container>
<ng-template #loader>
  <!-- Loader element -->
</ng-templtate>

Be aware this is a VERY simple example of this and is often better handle via some sort of state management.

Solution 3:[3]

All you need to know is whether the request is finished or not and set loading flag according to it.

AppComponent HTML

<ng-container>
 <loading-el *ngIf = "loading"></loading-el>
 <main-components *ngIf = "!loading"></main-components>
</ng-container>

Appcomponent.ts

loading = false;

getRecord() {
 this.loading = true;
 this.http.get(rec => {
  this.loading = false;
  ...operation...
 })
}

Solution 4:[4]

This is a pretty standard requirement and you have some options.

The simplest is to create a boolean property on your component and set it to true in the ngOnit hook. Here is a link that steps through it.

How to show spinner in angular 6

...as an alternative you could write an angular resolver to get your data prior to your component loading.

https://dzone.com/articles/understanding-angular-route-resolvers-by-example#:~:text=A%20Resolver%20is%20a%20class,may%20also%20like%3A%20Angular%20Resolvers.

Both require a loader graphic of some kind, the resolver allowing you to handle loading at an application level, which stops duplication in your components.

Solution 5:[5]

You actually don't need to manage a flag at the component level.

Use observables.

import { Component, OnInit } from '@angular/core';
import { from, Observable } from 'rxjs';

class Item {
  constructor(public name = 'New Item') {}
}

@Component({
  selector: 'my-app',
  template: `
    <button (click)="loadItems()">Load</button>
    <hr>
    <ng-container *ngIf="items$ | async as items; else loading">
      <div *ngFor="let item of items; let index = index">
        {{index+1}}. {{ item.name }}
      </div>
    </ng-container>
    <ng-template #loading>
      Loading...
    </ng-template>
  `,
})
export class AppComponent implements OnInit {
  items$: Observable<Item[]>;

  ngOnInit() {
    this.loadItems();
  }

  private loadItems() {
    // Simulate HTTP request
    const promise: Promise<Item[]> = new Promise((resolve) => {
      setTimeout(() => {
        resolve([new Item(), new Item(), new Item()]);
      }, 750);
    });

    // Where the magic happens
    // Reassign the observable, which will trigger the else
    // block in the template and display the loader.
    // Once it completes, it will display the list as normal.
    this.items$ = from(promise);
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tim Lepage
Solution 2 Ben Brookes
Solution 3 Ajeet Eppakayala
Solution 4 Darren Street
Solution 5 Dan