Ionic 4: "Loading Controller" dismiss() is called before present() which will keep spinner without dismissing
this is how I solved my issue..
I used a boolean variable "isLoading" to change to false when dismiss() is called. after present() is finished if "isLoading" === false (means dismiss() already called) then it will dismiss immediately.
also, I wrote the code in a service so I don't have to write it again in each page.
loading.service.ts
import { Injectable } from '@angular/core';
import { LoadingController } from '@ionic/angular';
@Injectable({
providedIn: 'root'
})
export class LoadingService {
isLoading = false;
constructor(public loadingController: LoadingController) { }
async present() {
this.isLoading = true;
return await this.loadingController.create({
// duration: 5000,
}).then(a => {
a.present().then(() => {
console.log('presented');
if (!this.isLoading) {
a.dismiss().then(() => console.log('abort presenting'));
}
});
});
}
async dismiss() {
this.isLoading = false;
return await this.loadingController.dismiss().then(() => console.log('dismissed'));
}
}
then just call present() and dismiss() from the page.
the example in question:
customer: any;
constructor(public loading: LoadingService, private customerService: CustomerService)
ngOnInit() {
this.loading.present();
this.customerService.getCustomer('1')
.subscribe(
customer => {
this.customer = customer;
this.loading.dismiss();
},
error => {
console.log(error);
this.loading.dismiss();
}
);
Here's how I've solved the same issue in my project. I use this service in the HTTP Interceptor to show the loader for all the REST API calls inside my app.
loading.service.ts
import {Injectable} from '@angular/core';
import {LoadingController} from '@ionic/angular';
@Injectable({
providedIn: 'root'
})
export class LoadingService {
constructor(public loadingController: LoadingController) {
}
async present(options: object) {
// Dismiss all pending loaders before creating the new one
await this.dismiss();
await this.loadingController
.create(options)
.then(res => {
res.present();
});
}
/**
* Dismiss all the pending loaders, if any
*/
async dismiss() {
while (await this.loadingController.getTop() !== undefined) {
await this.loadingController.dismiss();
}
}
}
In the original question context this could be used like below:
...
import {LoadingService} from '/path/to/loading.service';
...
customer: any;
constructor(public loadingService: LoadingService, private customerService: CustomerService)
ngOnInit() {
this.loadingService.present({
message: 'wait. . .',
duration: 5000
});
this.customerService.getCustomer('1')
.subscribe(customer => {
this.customer = customer;
this.loadingService.dismiss();
}
}
for Ionic 4 check this solution
Source Link
import { Component } from '@angular/core';
import { LoadingController } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
loaderToShow: any;
constructor(
public loadingController: LoadingController
) {
}
showAutoHideLoader() {
this.loadingController.create({
message: 'This Loader Will Auto Hide in 2 Seconds',
duration: 20000
}).then((res) => {
res.present();
res.onDidDismiss().then((dis) => {
console.log('Loading dismissed! after 2 Seconds');
});
});
}
showLoader() {
this.loaderToShow = this.loadingController.create({
message: 'This Loader will Not AutoHide'
}).then((res) => {
res.present();
res.onDidDismiss().then((dis) => {
console.log('Loading dismissed! after 2 Seconds');
});
});
this.hideLoader();
}
hideLoader() {
setTimeout(() => {
this.loadingController.dismiss();
}, 4000);
}
}