Work around for Ionic Modal focus trapping

We’re using Ionic 6.0.0-rc.0 with Angular, and want to also use some Angular components that create overlays with the Angular CDK.

When an Ionic Modal contains a component that opens a CDK overlay (e.g. a color picker), the inputs in that overlay cannot be focused.

My understanding is that Ionic Modals very intentionally trap focus, and the problem is that the Angular CDK overlays are appended to the document outside of the modal. I tried modifying the CDK overlay to use the modal as it’s container, but that throws off the positioning of elements inside the overlay.

The Angular CDK (and components that use it) are very useful in the Angular ecosystem so I’m really hoping there is a way for them to play nicely with each other.

Is there any configuration option to disable trapping focus, or to exclude certain elements from it? Or any other suggestions on how to have an overlay within a modal work OK?

Thanks!

1 Like

While you wait for better answers, I’d like to urge you not to nest modals, period.

With modern applications, the user expects to be in charge of what is getting done. Modals invert that, blocking the user’s freedom. As such, they should be as narrowly targeted as possible - they need to inform about some blocking situation, or get some crucial input that is absolutely necessary to open back up the garden of free interaction.

Sort of by definition, that doesn’t extend to “needing more than one of them at once”.

So if you want to mix Angular Material overlays and Ionic overlays, that’s fine, but I wouldn’t pop one overlay from inside another, regardless of what kind they are.

In addition to making your users less frustrated with the maze of twisty modals, you also have designed away your technical problem (along with the next 8 of them that are virtually guaranteed to show up, because modals aren’t designed to be nested).

I should’ve clarified, these CDK overlays I’m talking about are things such as a color picker, not a full modal on top of a modal. They are often “attached” to an input, not necessarily covering the entire page. There are many uses for overlays besides a modal.

Also unless I’m missing something, I can’t really avoid using the Ionic modals in the first place, since they are a pretty common part of workflows like create/edit. Yes they block the user’s freedom, but on a phone they are full screen and a very common part of mobile UX as far as I’m aware.

I have a similar issue with our modals.
For us we are creating items inside a modal, since you can be doing that from anywhere in our mobile application. And in this process we have modals used to edit fields.

What I do is just a timed hack:

   ngAfterViewInit (): void {
        setTimeout(() => this.input.setFocus(), 1000);
    }

It’s far from pretty, but I guess if you know what you are doing, you can get away with it.

We are using an editor (tinymce) inside an ion-modal which uses popups to assign links, etc. (actually just like this comment function in this forum, that is inside a modal) These popups have input fields that are blocked from writing because the focus gets stolen.
I see the point of @rapropos of not stacking modals, but there should be an option to avoid this restriction. It’s hard to argue to your client, that their desired UI is not implementable just BECAUSE :smiley:

I also ran into this issue, when using 3rd party (not Ionic) pickers. I also think that this does not count as nesting modals, opening a picker (date picker, color picker, select etc.) from a modal is standard UX. It also works out of the box with Ionic pickers.

Looking at the source I found that focus trapping is ignored if the ion-modal has the ion-disable-focus-trap css class set, which works fine for me.

This works with the css class applied dynamically, e.g. add it when the picker is shown, and remove it when the picker is closed. Example (using Mobiscroll date picker):

<ion-modal #myModal>
  <ng-template>
    <ion-content>
      <mbsc-datepicker
        (onOpen)="myModal.cssClass = 'ion-disable-focus-trap'"
        (onClose)="myModal.cssClass = ''"
      ></mbsc-datepicker>
    </ion-content>
  </ng-template>
</ion-modal>
2 Likes

Much obliged, saved my day.
It would be nice if the Ionic API provided easy configuration for focus trapping, but this will do for now.