Close a specific modal, is there a modal `id`?

Hi there,

how do we handle closing a specific modal in Ionic 5 and Vue?

I have seen some old answers mentioning a modal id property but I cannot find anything about it in the docs.

There is a dismiss() method on the modal instance but that would require having the modals globally available.

Before I implement my own solution, is the id property still available?

I tried using the id, but when closing a second modal I get the error

[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next 
  at <IonApp> 
  at <App>
warn @ runtime-core.esm-bundler.js:38
logError @ runtime-core.esm-bundler.js:211
handleError @ runtime-core.esm-bundler.js:203
callWithErrorHandling @ runtime-core.esm-bundler.js:157
flushJobs @ runtime-core.esm-bundler.js:384
Promise.then (async)
queueFlush @ runtime-core.esm-bundler.js:286
queueJob @ runtime-core.esm-bundler.js:280
run @ reactivity.esm-bundler.js:183
trigger @ reactivity.esm-bundler.js:189
set value @ reactivity.esm-bundler.js:761
removeTeleportedUserComponent @ index.esm.js:1477
removeViewFromDom @ index.esm.js:1499
detachComponent @ framework-delegate-4392cd63.js:1
eval @ ion-modal.entry.js:1
step @ tslib.es6.js:102
eval @ tslib.es6.js:83
fulfilled @ tslib.es6.js:73
Promise.then (async)
step @ tslib.es6.js:75
eval @ tslib.es6.js:76
__awaiter @ tslib.es6.js:72
e.dismiss @ ion-modal.entry.js:1
eval @ index-7a8b7a1c.js:1
Promise.then (async)
value @ index-7a8b7a1c.js:1
dismissOverlay @ overlays-28c23c35.js:1
dismiss @ overlays-28c23c35.js:1
dismiss @ modal-passwordless-send.vue:126
Object.onClick._cache.<computed>._cache.<computed> @ modal-passwordless-send.vue:7
eval @ runtime-dom.esm-bundler.js:347
callWithErrorHandling @ runtime-core.esm-bundler.js:154
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:163
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:173
invoker @ runtime-dom.esm-bundler.js:333
runtime-dom.esm-bundler.js:37 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'nextSibling')
    at nextSibling (runtime-dom.esm-bundler.js:37)
    at removeFragment (runtime-core.esm-bundler.js:4811)
    at remove (runtime-core.esm-bundler.js:4777)
    at unmount (runtime-core.esm-bundler.js:4763)
    at unmountComponent (runtime-core.esm-bundler.js:4835)
    at unmount (runtime-core.esm-bundler.js:4736)
    at Object.remove (runtime-core.esm-bundler.js:5130)
    at unmount (runtime-core.esm-bundler.js:4747)
    at patchKeyedChildren (runtime-core.esm-bundler.js:4558)
    at patchChildren (runtime-core.esm-bundler.js:4449)

Using the dismiss() method would close the most current open modal.

Iā€™m having a really tough time thinking of a situation where one would want multiple modals open at the same time.

2 Likes

I could give you a few scenarios.

For one-off actions, they are easier to implement and maintain than fully-fledged pages. No need to worry about routing, history or back button.

For example, we offer authentication via a modal, with multiple options.
By tapping login, a modal is shown with the auth choices. This is helpful since the login modal can be opened from a drawer, regardless of what page the user is on. (or pop up when an action requires auth).

1 - On a passwordless auth flow, a user tries to login via email, so another modal asks for email. Once the email is sent, a third modal shows on top of it, asking for a code. We cannot close the previous ones yet, as the user might not get the code in time or whatever, so they can request a new one without starting over. Once they enter the code and are authenticated, all modals (3) get dismissed
ā†’ Login/Email/Code

2 - Same goes with a Google login. We merge multiple accounts based on email matches, so we show a modal to the user when there is a clash, again asking to confirm their identity by entering a code we sent by email. Once the user does that, both modals get dismissed.
ā†’ Login/Confirmation Code

3 - Same as 2, but if the user is an admin, they need to confirm their admin credentials. On success, both modals get dismissed
ā†’ Login/Confirm Credentials.

The authentication is always performed on top of what page the user is on, to avoid disruption of what they are doing.

Anyway, it looks like id is not available so we will write our own modalsHandler component.

Thanks

Hello,
Late but still available

Got a similar issue and found this

Check bug: modalController.dismiss () does not close the modal if several modals are created but not presented. Ā· Issue #21173 Ā· ionic-team/ionic-framework Ā· GitHub

ā€œa situation where one would want multiple modals open at the same time.ā€
example : a modal with a component in which there is a ion-datetime ( opening as modal ) ( still in V5, not try V6 )

Cheers

We ended up writing a modal handler service


export const modalsHandlerService = {

    modals: {
        login: null,
        passwordlessSend: null,
        passwordlessLogin: null,
        confirmPassword: null,
        confirmEmail: null
    },
    set login (modal) {
        this.modals.login = modal;
    },
    get login () {
        return this.modals.login;
    },
    set passwordlessSend (modal) {
        this.modals.passwordlessSend = modal;
    },
    get passwordlessSend () {
        return this.modals.passwordlessSend;
    },
    set passwordlessLogin (modal) {
        this.modals.passwordlessLogin = modal;
    },
    get passwordlessLogin () {
        return this.modals.passwordlessLogin;
    },
    set confirmPassword (modal) {
        this.modals.confirmPassword = modal;
    },
    get confirmPassword () {
        return this.modals.confirmPassword;
    },
    set confirmEmail (modal) {
        this.modals.confirmEmail = modal;
    },
    get confirmEmail () {
        return this.modals.confirmEmail;
    },
    //dismiss all modals
    dismissAll () {
        Object.values(this.modals).forEach((modal) => {
            if (modal) {
                modal.dismiss();
            }
        });
    }
};


We assign each modal like

modalsHandlerService.passwordlessSend = await modalController.create({...});

then we can call

modalsHandlerService.dismissAll();
2 Likes

Thanks for the update @mirko77; I am glad to hear that this was able to help achieve the functionality with modals that you were looking for. I am going to mark this answer as a solution so that others with similar questions can find your post more easily.

1 Like