Dismiss a LoadingController

Hi,
I switched to Ionic v4 recently and I have some troubles with LoadingController.

I do not succeed to cancel it (when I got an error).

I got my function in my component :

async loadingLogin() {
    const loading = await this.loadingController.create({
      message: 'Connexion ...',
      showBackdrop: true,
      id: 'login'
    });
    return await loading.present();
  }

When the user log in, I launch the loadingController. If the login succeeds, I can cancel it.
But if it fails, I canā€™t cancel the spinner :

  @Input() set pending(isPending: boolean) {
    if (isPending) {
      this.loadingLogin();
    } else {
      this.loadingController.dismiss('login');
    }
  }

  @Input() set error(error: HttpErrorResponse) {
    if (error) {
      this.loadingController.dismiss(null, null, 'login');
      this.loadingController.dismiss('login');
    }
  }

Here is my package.json and I got the angular type of Ionic project :

  "dependencies": {
    "@angular/common": "~6.1.1",
    "@angular/core": "~6.1.1",
    ...
    "@ionic-native/core": "5.0.0-beta.15",
    "@ionic-native/network": "5.0.0-beta.15",
    "@ionic-native/splash-screen": "5.0.0-beta.15",
    "@ionic-native/status-bar": "5.0.0-beta.15",
    "@ionic/angular": "4.0.0-beta.7",
    ...
  },
1 Like

Hi, the problem is that you are dismissing the controller and you need to dismiss the loading instance. For that I recommend you save the loading instance in a global variable and then dismiss it:

let loading: Loading = null;

loadingLogin() {
     this.loading = this.loadingController.create({
      message: 'Connexion ...',
      showBackdrop: true,
    });
    this.loading.present();
  }

@Input() set pending(isPending: boolean) {
    if (isPending) {
      this.loadingLogin();
    } else {
      this.loading.dismiss();
    }
  }

  @Input() set error(error: HttpErrorResponse) {
    if (error) {
        this.loading.dismiss();
    }
  }
2 Likes

Hi,
Thank you for your answer but unfortunately itā€™s not working.

loadingLogin2() {
    this.loading2 = this.loadingController.create({
      message: 'Connexion ...',
      showBackdrop: true,
    });
    this.loading2.present();
  }

I got the error message and fall in a loop :

ERROR TypeError: this.loading.present is not a function

I think itā€™s more related to the fact that I created an angular type project :

ionic start myApp super --type=angular

Because some methods or values described in the documentations do not exist or are not the same in my library.

import { LoadingController } from '@ionic/angular';
// example from the documentation : https://beta.ionicframework.com/docs/api/loading/
async presentLoading() {
    const loading = await this.loadingController.create({
      content: 'Hellooo', // For me 'content' does not exist, it's 'message' instead
      duration: 2000
    });
    return await loading.present();
  }

the optional value dismissOnPageChange described in the doc does not exist.

I may not have the right documentation.

1 Like

Sorry, I supposed that you were in ionic 3. Try this:

async presentLoading() {
    this.loading = await this.loadingController.create({
      content: 'Hellooo',
      duration: 2000
    });
    return await this.loading.present();
}
2 Likes

@shitsod were you able to dismiss the loading controller? I just switched to ionic 4 and have the exact same issue in my login page. Any help would be greatly appreciated!!!

1 Like

using a class variable worked for me

async presentLoading() {
    this.loading = await this.loadingController.create({
      content: 'Hellooo',
      duration: 2000
    });
    return await this.loading.present();
}

call this.presentLoading() when you want to show the loader. When you want to dismiss the loader, do:

this.loading.dismiss();

it is very irritating that the docs for v4 are incomplete.

6 Likes

I donā€™t think you should be using the instance returned by create(). Every time Iā€™ve run into a problem with loading messages not dismissing like I expect, itā€™s been an async problem. Make sure you arenā€™t initiating your AJAX request until after the modal is displayed. The only way to to that is put your http call after the await or in then of present().

It happens quite often that the http request will error out faster than the modal code has run and you are trying to dismiss a modal that doesnā€™t exist yet. Eventually the loader will display, but youā€™ve already tried to dismiss it, so itā€™s there to stay.

4 Likes

Do anyone got the solution ?

please share working solution.

Thanks

1 Like

Alernative solution

presentLoading() {
this.loadingController.create({
message: ā€˜Loadingā€¦ā€™
}).then((res) => {
res.present();
// call your methods
this.getInfoFromRest().then((d) => {
res.dismiss();
}).catch((er) => {
res.dismiss();
})
});
}

tried everthing, the loader.dismiss after error are not even dismissed, and triggers an error of undefinedā€¦

1 Like

so can you share your code if its not working. I can dismiss it without issues. Sometimes you need to be careful to call .dismiss() only after the indicator fully loaded. But it works fine.

1 Like

For the issue when after error its not dismissing - good practice is to call .dismiss from within your error handler.

1 Like

I place it right in the error handler and its shooting undefined which does not makes sense at all

Agreed, this is likely the problem, thereā€™s nothing wrong with using dismiss on loadingController.

1 Like

Was facing same issue. Used callbacks to solve.
Please refer following code.

presentLoadingAndCall(message: string, cb, data) {
const loading = this.loadingCtlr.create({
message: message,
spinner: ā€œbubblesā€,
translucent: true
}).then(loading => {
loading.present();
this[cb](data, loading);
});
}

1 Like

After trying everything, hereā€™s what I finally came up with. Seems to be working well so far.

Trying to make use of setInterval with a 500ms interval. I also tried to keep the function non-async so that it may be easily used in the consuming end.

import { Injectable } from '@angular/core';
import { LoadingController } from '@ionic/angular';

@Injectable({ providedIn: 'root' })
export class UiService {
    constructor(private loading: LoadingController) { }


    private loader: HTMLIonLoadingElement;
    private loaderLoading = false;

    public showLoading(message: string) {
        this.loaderLoading = true;
        this.loading.create({
            message,
            showBackdrop: true
        }).then(load => {
            this.loader = load;
            load.present().then(() => { this.loaderLoading = false; });
        });
    }

    public dismissLoading() {
        const interval = setInterval(() => {
            if (this.loader || !this.loaderLoading) {
                this.loader.dismiss().then(() => { this.loader = null; clearInterval(interval)});
            } else if (!this.loader && !this.loaderLoading) {
                clearInterval(interval);
            }
        }, 500);
    }
}
2 Likes

Iā€™m confused. Doesnā€™t this just make the user wait for half a second for no reason?

Also not seeing the point of this.

1 Like

Fantastic solution !!! With your code finally Iā€™ve could implement correctly this functionality. Probably there are other solutions but this one works for me after many failed attempts. Thank you very much !!!

1 Like

i just used this.loadingController.dismiss(); and it works fine.

4 Likes

I solved by adding a timeout for the default controller itself, but its very strange where sometimes it complains overlay does not exist even though the controller is being called and being dismissed