How to handle hardware Back Button on Ons-Dialog?

I had the same problem when using the dialog component from within an ons-navigator object. In order to make it work, I had to disable the default back button handler of the dialog and have the Navigator object handle it instead.

Here is the code I made, hope it helps:

ons.createDialog('dialogs/yourDialog.html').then(function(dialog) {
    dialog.getDeviceBackButtonHandler().disable();

    var f = function(event) {
        dialog.hide();
        myNavigator.getDeviceBackButtonHandler().setListener(function(event) { 
            try{
                myNavigator.popPage(); 
            }
            catch (err){
                event.callParentHandler();
            }
        });
    } 
    myNavigator.getDeviceBackButtonHandler().setListener(f);
    dialog.show({parentScope: $scope});
});

Brief explanation:

  • Disable dialog back button handler (this is what is causing errors)
  • When disabled, the back button will be handled by the next node that has a back button handler (myNavigator, in this case) that works fine.
  • Change the event listener of myNavigator when the dialog is shown, to hide the dialog.
  • After hiding it, I try to restore its default functionality. It´s a Navigator object, so popPage should be the default action, and, if the page stack is empty (what throws an error) we will call the parent handler (that will, usually, get you out of the app)

The default deviceButton behavior for dialog is hiding. In order to change it you can do it in this way:

ons.bootstrap().controller('MyController', function($scope) {
    $scope.hideDialog = true;
    $scope.changeMode = function() {
        $scope.hideDialog = !$scope.hideDialog;
        if ($scope.hideDialog) {
            console.log('now hiding');
            $scope.dialog.getDeviceBackButtonHandler().setListener(function() { $scope.dialog.hide();});
        } else {
            console.log('now printing');
            $scope.dialog.getDeviceBackButtonHandler().setListener(function() { console.log('hey!');});
        }
    };

    ons.ready(function() {
        ons.createDialog('dialog.html').then(function(dialog) {});
    });
});

And this is the example HTML:

<body ng-controller="MyController"> 
    <ons-template id="dialog.html">
      <ons-dialog var="dialog" cancelable>
        <p>Mode: {{ hideDialog ? "Hide Dialog" : "ConsoleLog Hey" }}</p>
        <p><ons-button ng-click="changeMode()">Change Mode</ons-button></p>
      </ons-dialog>
    </ons-template>

    <ons-page>
        <p><ons-button ng-click="dialog.show()">Show Dialog</ons-button></p>
    </ons-page>
</body>

I just tested that in Onsen UI 1.3.8 and Monaca, seems working well.

Hope it helps!