Ionic version: (check one with "x")
[ ] 1.x
[x ] 2.x
I'm submitting a ... (check one with "x")
[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/
Current behavior:
With LoadingController currently been displayed, pressing the hardware back button takes you to the previous view with the loadingController still been shown.
Expected behavior:
LoadingController should prevent any hardware back button press from working OR dismiss the loadingController when the hardware back button press takes user to the previous view.
Steps to reproduce:
Push to a new view
Call loadingController.present()
Press the hardware back button while loadingController is still displayed
Related code:
// push to a new view
this.navCtrl.push(Filter);
// Call LoadingController
let loader = this.loadingCtrl.create({
content: "Please wait...",
duration: 10000 // to enable it still longer on the screen.
});
loader.present();
Other information:
Ionic info: (run ionic info from a terminal/cmd prompt and paste output below):
Cordova CLI: 6.5.0
Ionic Framework Version: 2.0.1
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.1.1
ios-deploy version: 1.9.0
ios-sim version: 5.0.13
OS: macOS Sierra
Node Version: v6.9.4
Xcode version: Xcode 8.2.1 Build version 8C1002
@manucorporat I thought this was solved back in rc4 :(
Apparently the issue still happens. It would be best to prevent the backbutton action while loading just as it does when presenting an alert. Would you consider taking a look?
Thank you!
any update on this please?
Hi,
Any update....???
I am also facing same issue. Any update??
@manucorporat Any Update on this issue ?
and now I'm facing same issue, I hope will be update as soon. thanks
thanks :D
On 4 Dec 2017 8:57 a.m., "buchori28" notifications@github.com wrote:
and now I'm facing same issue, I hope will be update as soon. thanks
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/ionic/issues/10484#issuecomment-348854825,
or mute the thread
https://github.com/notifications/unsubscribe-auth/APjGarR7RShpf6RL8MwyDpRvJzBHFVohks5s8223gaJpZM4MENWX
.
I'm also facing this issue.
I've found one workaround, for those who are calling loadings inside pages, not services:
this.platform.registerBackButtonAction(() => {
let nav = this.app.getRootNav();
let activeView: ViewController = nav.getActive();
if (activeView != null) {
if (typeof activeView.instance.backButtonAction === 'function')
activeView.instance.backButtonAction();
else if (nav.canGoBack())
nav.pop();
}
})
loading: Loading;
this.loading = this.loadingCtrl.create({...});
this.loading.present();
backButtonAction() {
if (this.loading && this.loading.index != -1) {
this.loading.dismiss();
} else {
// you can have another conditions here
this.navCtrl.pop();
}
}
However, this only works for loadings we call inside pages. I have a case where I need to show a loading inside a service. I can't manipulate the backbutton inside the service (only in app.component, where I don't have a reference for the loading).
This is a very severious bug, as it impacts directly on the user experience. Ionic team, you should fix this ASAP.
cli packages:
@ionic/cli-utils : 1.19.0
ionic (Ionic CLI) : 3.19.0
global packages:
cordova (Cordova CLI) : 7.0.1
local packages:
@ionic/app-scripts : 3.1.2
Cordova Platforms : android 6.2.2
Ionic Framework : ionic-angular 3.9.2
System:
Node : v8.9.3
npm : 5.6.0
OS : Windows 10
@allanpoppe could you not just use event emitters to tell the service to hide the loader from the main app component? I'm struggling with this too ATM
@romain10009 eventually I changed my approach to something like you said, with some other cool stuff.
The ideia is to have a unique Loading inside a loadingService (or another service you usually imports in all pages and/or other services).
loading.service.ts
isLoading: boolean = false;
constructor(private loadingCtrl: LoadingController) {
const this_ = this;
this.platform.ready().then(function () {
this_.configBackButton();
});
}
showLoading(message: string = "") {
this.loading = this.loadingCtrl.create({
content: message,
enableBackdropDismiss: true
});
this.loading.present();
this.isLoading = true;
return this.loading;
}
async hideLoading() {
if (this.isLoading) await this.loading.dismiss();
this.isLoading = false;
}
app.component.ts
constructor(private app: App, private loadingService: LoadingService, ...) {
}
async configurarBackButton() {
this.platform.registerBackButtonAction(() => {
if (this.loadingService.isLoading) {
this.loadingService.hideLoading();
} else {
const nav = this.app._appRoot._getActivePortal() || this.app.getRootNav();
const activeView: ViewController = nav.getActive();
if (activeView) {
if (typeof activeView.instance.backButtonAction === 'function')
activeView.instance.backButtonAction();
else if (activeView.isOverlay)
activeView.dismiss();
else if (nav.canGoBack())
nav.pop();
}
}
});
}
somePage.ts or someService.ts
async someMethod() {
let showLoading = true; // this will help the application only show the loading if the operation tooks too long
let continueExecution = true; // this will help do the trick to prevent the application from doing things if the user clicked the back button or the loading's backdrop
let loading: Loading;
try {
setTimeout(() => {
if (showLoading) {
loading = this.loadingService.showLoading("Saving..."); // or another loading message
loading.onDidDismiss(() => { continueExecution = false }); // this does the prevent execution trick
}
}, 300);
await this.save(); // the method you want to wait
if (!continueExecution) return; // prevent execution trick
... more operations after saving
} catch (e) {
this.errorService.manipulateError(e); // log the error in the database and/or show an error message
} finally {
showLoading = false;
await this.loadingService.hideLoading();
}
}
This issue also happens with ionic v3.20.
Credits to Ionic forum post here - Create a wrapper for loader instead
Note that using a provider that interacts with view layer isn't really what provider should do. Read the discussion here. Personally, IMO it's up to your preference. I rather follow the principle of DRY.
Step 1:
ionic g provider loader
This step will create a provider class named LoaderProvider in your project.
Step 2:
import {Injectable} from "@angular/core";
import {Loading, LoadingController, LoadingOptions, Platform} from "ionic-angular";
@Injectable()
export class LoaderProvider {
constructor(
private loadingCtrl: LoadingController,
private platform: Platform
) { }
create(opts?: LoadingOptions): Loading {
let subscription;
let loading = this.loadingCtrl.create(opts);
loading.willEnter.subscribe(() => {
subscription = this.platform.registerBackButtonAction(() => {
console.log('back button pressed');
}, 10); // make sure there is no other backButton action with a priority > 10
});
loading.onDidDismiss(() => {
subscription();
});
return loading;
}
}
Hello,
you can dismiss loader on hardware back button and also on page's back button by simply adding
# dismissOnPageChange: true on loading controller like below:-
loadingModal: any;
this.loadingModal = this.loadingCtrl.create(
{
spinner:'hide',
content: '<img src="assets/icon/loader.gif">',
dismissOnPageChange: true
});
this.loadingModal.present();
This issue has been automatically identified as an Ionic 3 issue. We recently moved Ionic 3 to its own repository. I am moving this issue to the repository for Ionic 3. Please track this issue over there.
If I've made a mistake, and if this issue is still relevant to Ionic 4, please let the Ionic Framework team know!
Thank you for using Ionic!
Issue moved to: https://github.com/ionic-team/ionic-v3/issues/255