Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 4: "Loading Controller" dismiss() is called before present() which will keep spinner without dismissing

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 already have the data, the "dismiss()" is called before the "create()" and "present()" is done which will keep the spinner without dismissing...

I tried to call the data inside "loadingController.present().then()", but that caused the data to be slower...

is this a bug? how to solve the this issue?

Example of my code:

customer: any;  constructor(public loadingController: LoadingController, private customerService: CustomerService)  ngOnInit() {   this.presentLoading().then(a => consloe.log('presented'));   this.customerService.getCustomer('1')   .subscribe(customer => {     this.customer = customer;     this.loadingController.dismiss().then(a => console.log('dismissed'));   } }  async presentLoading() {   const loading = await this.loadingController.create({     message: 'wait. . .',     duration: 5000   });   return await loading.present(); } 
like image 773
rami bin tahin Avatar asked Sep 30 '18 03:09

rami bin tahin


People also ask

How do you dismiss loader in ionic 4?

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 already have the data, the "dismiss()" is called before the "create()" and "present()" is done which will keep the spinner without dismissing...

How do you add loading animations in ionic?

const loading = await this. loadingController. create({ message: '<ion-img src="/assets/svg/shopping. svg" alt="loading..."></ion-img>', cssClass: 'scale-down-center', translucent: true, showBackdrop: false, spinner: null, duration: 2000 });

What is the ionic ionic loading controller?

The ion-loading controller is a fabulous overlay that refrains the user’s interaction while current requests are being processed. The loading indicator in Ionic comes on top of the application’s content and can be removed or dismissed to continue the user interaction with the app. Open terminal, type and then execute command to install Ionic CLI:

How to dismiss the loading indicator after a specific amount of time?

The loading indicator can be dismissed automatically after a specific amount of time by passing the number of milliseconds to display it in the duration of the loading options. To dismiss the loading indicator after creation, call the dismiss () method on the loading instance.

How to pass the spinner name to the loading indicator?

The spinner name should be passed in the spinner property. If a value is not passed to spinner the loading indicator will use the spinner specified by the platform. The loading indicator can be dismissed automatically after a specific amount of time by passing the number of milliseconds to display it in the duration of the loading options.


2 Answers

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();     }   ); 
like image 156
rami bin tahin Avatar answered Sep 21 '22 08:09

rami bin tahin


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();   } } 
like image 20
Andrii S. Avatar answered Sep 22 '22 08:09

Andrii S.