useModalLifecycle()
useModal() renders any component you give it. It passes the component a modelValue, and settles open() and close() on the events the component emits once it has opened or closed. useModalLifecycle() emits them for you, so your component only shows and hides itself. <VueFinalDialog> is built on it.
Usage
Declare modalComponentProps and ModalComponentEmits, and give useModalLifecycle() an open and a close hook. A hook that returns a promise holds opened or closed back until it settles, for example until a transition ends:
<script setup lang="ts">
import type { ModalComponentEmits } from 'vue-final-modal'
import { ref } from 'vue'
import { modalComponentProps, useModalLifecycle } from 'vue-final-modal'
const props = defineProps(modalComponentProps)
const emit = defineEmits<ModalComponentEmits>()
const dialog = ref<HTMLDialogElement>()
const { isOpen, reportClosed } = useModalLifecycle(props, emit, {
open: () => dialog.value!.showModal(),
close: () => dialog.value!.close(),
})
function onClose() {
if (!dialog.value!.open)
reportClosed()
}
</script>
<template>
<dialog ref="dialog" @cancel.prevent="isOpen = false" @close="onClose">
<slot />
</dialog>
</template>
const { open } = useModal({ component: MyDialog })
await open() // 'opened'
The hooks run once the component has mounted and rendered the new state. The browser may close the dialog on Esc although cancel was prevented, which onClose reports. It skips the close event of a dialog opened again before the event fired.
Return value
isOpen: whether the modal is open. Set it to open or close the modal from inside, for example from a close button:beforeOpenorbeforeCloseis emitted first, andupdate:modelValueafter.reportClosed(): reports a modal that already closed by itself, such as a dialog a<form method="dialog">closed, sobeforeCloseis not asked.toggle(show?): opens or closes the modal and resolves once it has, like useVfm().toggle(). Called while the modal is heading there, it settles with that change.status: a read-only ref of where the modal is,'closed','opening','opened'or'closing', like the status of useModal().
What it guarantees
Your component's open() and close() resolve with the same results as those of <VueFinalModal>:
'opened'and'closed'once the hook settled,'stopped'whenbeforeOpenorbeforeClosecalledevent.stop(), which also writes the previous value back tov-model,'toggled-again'when the modal was toggled again before its hook settled: the late hook does not emitopenedorclosed,'destroyed'when the component unmounted before its hook settled.
Events
ModalComponentEmits lists the events useModalLifecycle() emits: update:modelValue, beforeOpen, opened, beforeClose and closed, plus the internal _opened, _closed, _stopped and _status that useModal() listens to. In the Options API, use emits: modalComponentEmits.
Declare them only on the component that shows the modal. A wrapper around <VueFinalDialog> or <VueFinalModal> that declares them swallows the internal listeners of useModal(): let them fall through to the inner component instead.