'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.
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 |