Prevent closing of multiple modal / alert / picker / etc. on Escape key


#1

Hi,

Now that Ionic can be used on desktop, but also for the edge case of a keyboard connected to a mobile device, the ESCAPE key can be used to close:

  • <ion-action-sheet>
  • <ion-popover>
  • <ion-loading>
  • <ion-picker>
  • <ion-toast>
  • <ion-modal>
  • <ion-alert>

Unfortunately, each of these overlay categories (actually, their associated controllers) separately listens to the body’s ESCAPE key up event.
This means that if your app has several of these categories simultaneously opened (e.g. a modal and an alert / picker / etc.), the last instance of each category will be closed when user presses ESCAPE.
Whereas the usual expected behaviour is that only the latest / top-most overlay is closed (e.g. only the alert closes, but the below modal remains open).
Example: http://plnkr.co/edit/LjQ1RJwjPLym9jm63yag?p=preview

This has already been reported a while ago:

A workaround would be to handle the ESCAPE key up event at the app level, and prevent Ionic from automatically closing the overlays. That way, we can select which overlay is closed.

document.body.addEventListener('keyup', (event) => {
  if (event.keyCode === 27) { // ESCAPE key
    event.preventDefault();
    // Prevent Ionic from automatically closing overlays.
    event.stopImmediatePropagation();

    // Find all overlay elements.
    const escapeClosable = document.querySelectorAll(
      'ion-action-sheet, ion-popover, ion-loading, ion-picker, ion-toast, ion-modal, ion-alert'
    );
    if (escapeClosable.length === 0) {
      return;
    }
    // Find the latest element, i.e. the bottom-most in the DOM tree.
    const topMostClosable = escapeClosable[escapeClosable.length - 1];
    topMostClosable.dismiss();
  }
});

Example: http://plnkr.co/edit/ipVwtdqwgdvKYFfTqBLB?p=preview

The first part of this workaround can obviously be used to prevent the ESCAPE key from closing any of the overlays (Stop Modal Close on Escape Key Press), since there is currently no option to turn off this feature in Ionic.

Hope this helps.