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
          }
        });
      ));
    });
    

  • Onsen UI

    @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 include cordova.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.


  • Onsen UI

    @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.


  • Onsen UI

    @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


Log in to reply