I used \"Ionic Loading Controller\" to show a spinner until the data is retrieved then it calls \"dismiss()\" to dismissed it. it works fine, but sometimes when the app alre
CHECK THIS OUT!
After reading through these solutions I have come up with a solution that prevents loaders from stacking etc. It works great!
import { Injectable } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { LoadingOptions } from '@ionic/core';
import { TranslateService } from '@ngx-translate/core';
import { isNil } from 'lodash-es';
import { BehaviorSubject } from 'rxjs';
import { filter } from 'rxjs/operators';
enum LoadingTypeEnum {
show,
hide,
message,
}
@Injectable({
providedIn: 'root',
})
export class LoadingService {
/**
* this is a special behavior subject we can use on an inital load to show or hide a background etc.
* EXAMPLE: on inital profile load, we might want to have ngIf on an overlay and simply listen for this event.
*/
public appLoaded$ = new BehaviorSubject(false);
public loading$: BehaviorSubject<{ type: LoadingTypeEnum; data?: any }> = new BehaviorSubject({ type: LoadingTypeEnum.hide });
loadingState: { type: LoadingTypeEnum; data?: any } = null;
public loading: HTMLIonLoadingElement = null;
public loaderLoaded = false;
public i;
public spinningUp = false;
constructor(private loadingController: LoadingController, private translate: TranslateService) {
const l$ = this.loading$.pipe();
l$.pipe(filter((l) => l.type === LoadingTypeEnum.show)).subscribe((l) => this.showLoading(l.data));
l$.pipe(filter((l) => l.type === LoadingTypeEnum.hide)).subscribe(() => this.hideLoading());
}
show(opts?: LoadingOptions) {
if (isNil(opts)) {
opts = {
message: 'Please wait...', // this.translate.instant('PLEASE_WAIT'),
};
}
this.loading$.next({ type: LoadingTypeEnum.show, data: opts });
}
hide() {
this.loading$.next({ type: LoadingTypeEnum.hide });
}
message(m: string) {
this.loading$.next({ type: LoadingTypeEnum.message, data: m });
}
private async showLoading(opts: LoadingOptions) {
if (!this.loading && !this.spinningUp) {
this.spinningUp = true;
this.loading = await this.loadingController.create(opts);
await this.loading.present();
this.spinningUp = false;
}
}
private async hideLoading() {
const t = setTimeout(() => {
if (this.loading && !this.spinningUp) {
this.loading.dismiss().then(() => {
this.loading = null;
this.spinningUp = false;
clearTimeout(t);
});
}
}, 1000);
}
}