Notice: The Monaca & Onsen UI Community Forum is shutting down.
For Onsen UI bug reports, feature requests and questions, please use the Onsen UI GitHub issues page. For help with Monaca, please contact Monaca Support Team.
Thank you to all our community for your contributions to the forum. We look forward to hearing from you in the new communication channels.
Onsen Dialog not closed by Android back button
-
Hi,
I ran into a little problem while using the onsen dialog in my app.I use the android backbutton in order to navigate back in my app, and when I’m on the home page, a back button click would show a prompt for the user, whether they want to close the app or not.
To get this working, I had to override the default back button behaviour, and I found some tutorials for that. That works nicely.However, I just noticed that even though my ons-dialogs are specified as cancelable, i am not able to use the backbutton to close / hide them.
Here’s my index.js script where I have my backbutton handler:
myApp.run(['$rootScope', function($rootScope) { document.addEventListener('deviceready', function() { // Handle the Cordova pause and resume events document.addEventListener( 'pause', onPause.bind( this ), false ); document.addEventListener( 'resume', onResume.bind( this ), false ); // TODO: Cordova has been loaded. Perform any initialization that requires Cordova here. ons.disableDeviceBackButtonHandler(); document.addEventListener("backbutton", onBackKeyDown, false); }, false); }]); var AlreadyFiredBackButton = false; function onBackKeyDown(e) { try { if(AlreadyFiredBackButton == false) { AlreadyFiredBackButton = true; if(myNavigator.topPage.name=="home.html") { ons.notification.confirm({ message: 'Are you sure you want to close?', title: 'Close app', buttonLabels: ['Yes','No'], callback: function(idx) { switch (idx) { case 0: AlreadyFiredBackButton = false; try{ if (navigator.app) { navigator.app.exitApp(); } else if (navigator.device) { navigator.device.exitApp(); } } catch(err) { } break; case 1: AlreadyFiredBackButton = false; break; } } }); } else { try { AlreadyFiredBackButton = false; myNavigator.popPage(); return; } catch(err) { AlreadyFiredBackButton = false; } try { AlreadyFiredBackButton = false; myNavigator.resetToPage('home.html'); return; } catch(err2) { AlreadyFiredBackButton = false; } } } } catch(pageerror) { AlreadyFiredBackButton = false; } }
Here’s my index.html where I’ve specified my login dialog:
<ons-template id="loginform.html"> <ons-dialog var="loginform" cancelable ng-controller="AppController"> <ons-toolbar inline> <div class="center"> Change Credentials </div> </ons-toolbar> <div class="login-form-div"> <p> <input placeholder="Username" id="username" ng-model="email" class="text-input"> </p> <p> <input type="password" placeholder="Password" id="password" ng-model="password" class="text-input"> </p> <div style="text-align: center" class="content-padded"> <ons-button style="width:48%;" ng-click="loginform.hide();">Cancel</ons-button> <ons-button style="width:48%;" ng-click="saveCredentials(lfusername, lfpassword);">Save</ons-button> </div> </div> </ons-dialog> </ons-template>
Any ideas why the ons-dialog is not disappearing when hitting the backbutton on android?
-
@dldpower2plan This may not be the issue, but try removing the template tags from around your dialog tags. In the docs and examples by Onsen, alerts / dialogs / etc, do not use a template as they stand alone.
http://tutorial.onsen.io/?framework=vanilla&category=Reference&module=dialog
-
Hi!
The examples for AngularJS also have the one with the templates.
I’m using the templates, because the other version was not working for me if I wanted to add a $scope variable to it.
But nevertheless, it shouldn’t make any difference. The important thing is, that the back button is ignored, the popover remains on the screen and the page is changed in the background.
-
@dldpower2plan The reason I suggest that is, with my understanding of Onsen, a dialog in a template resolves as nested templates and while it should work when pushed to the stack, it may mess up the order. Regardless, I see you are only calling a popPage in your custom backButton function and dialogs require hide. As stated in the docs, a more appropriate way is to do the following:
var page = myNavigator.topPage; page.onDeviceBackButton = function(event) { console.log('Hardware back button!'); event.callParentHandler(); // Calls the parent handler (navigator handler in this case) };
Also, a simpler way to handle the exit without the need to do all the nested if’s:
// Set a new handler ons.setDefaultDeviceBackButtonListener(function(event) { ons.notification.confirm('Do you want to close the app?') // Ask for confirmation .then(function(index) { if (index === 1) { // OK button navigator.app.exitApp(); // Close the app } }); )); });
-
@dldpower2plan The default behavior for the device back button is already like that. Closes dialogs, side menus and pops pages if needed. If there’s nothing like that to do, it closes the app. I think the second snippet posted by @munsterlander should be enough to add a prompt before closing the app.
For the default behavior is necessary to includecordova.js
but I guess you are already aware of that.
-
@munsterlander Thank you for the help, but when I tried the code suggested by you, i didn’t get any reaction from my mobile app, whatsoever.
I even took it from the Onsen docs (which have an error on line 8 for the second snippet, btw Onsen team), and it just keeps ignoring it.Here’s my index.js file after some slight modifications:
(function () { "use strict"; //document.addEventListener( 'deviceready', onDeviceReady.bind( this ), false ); myApp.run(['$rootScope', function($rootScope) { document.addEventListener('deviceready', function() { ons.enableDeviceBackButtonHandler(); // Set a new handler ons.setDefaultDeviceBackButtonListener(function(event) { if(myNavigator.topPage.name=="home.html") { ons.notification.confirm('Do you want to close the app?') // Ask for confirmation .then(function(index) { if (index === 1) { // OK button navigator.app.exitApp(); // Close the app } }); } else { myNavigator.popPage(); //here I tried event.callParentHandler(); as well } }); }, false); }]); ...handlers for onPause, onResume etc.... }
Using the event.callParentHandler(); method in the else part threw the following error:
Cannot read property 'deviceBackButtonHandlerId' of undefined
myNavigator.popPage(); at least closes the dialog / popover, but it also goes back to the previous page, so I’m still not quite there.
I am also explicitly loading a cordova.js file (that I took from the platform directory while using the PhoneGap serve) if that makes a difference.
-
@dldpower2plan Can you tell me what happens in this app when you push a page and then press the device back button 3 times?
In my phone it closes the dialog, then pops the page and then shows a prompt asking if I want to close the app.
-
@Fran-Diox I just took the exact same code from the CODEPEN, made it into an app, built it with PhoneGap build, and when I press the back button on the second page, it just closes the application immediately.
-
@dldpower2plan What device and Android version do you have? Are you using Crosswalk?
-
Hi Guys,
Can you help me to post example on how to customize back button behavior using angular2?I am sorry, I am unable to figure out how to use ons object, or onDeviceBackButton on angular2.
Thank you
-
this works for me
onDeviceReady: function() { this.receivedEvent('deviceready'); document.addEventListener("backbutton", onBackKeyDown, false); } function onBackKeyDown() { if(document.querySelector('ons-modal').visible){ document.querySelector('ons-modal').hide(); e.preventDefault(); }}
-
This post is deleted!