I implemented a composable which can mount a component just inside a typescript function without defining it in the <template>
section.
export const useMountDialog = () => {
const appContext = inject<AppContext>('$useMountDialog')
if (!appContext) {
throw new Error(
'Could not find app context. Make sure to provide the app instance.'
)
}
const mountDialog = <T extends { new (...args: any[]): any }>(
component: T,
props: ExtractPropTypes<InstanceType<T>>
) => {
const container = document.createElement('div')
const vNode = h(component, props)
vNode.appContext = appContext
render(vNode, container)
const unmount = () => {
console.log('Unmount')
// document.body.removeChild(container);
render(null, container)
}
document.body.appendChild(container)
}
const mountDialogAndWait = async <T extends { new (...args: any[]): any }>(
component: T,
props: ExtractPropTypes<InstanceType<T>>,
data?: any
) => {
const confirmDialogReturn = useConfirmDialog()
const extendedProps = { ...props, confirmDialogReturn }
mountDialog(component, extendedProps)
return await confirmDialogReturn.reveal(data)
}
return { mountDialog, mountDialogAndWait }
}
Currently the container div does not get removed from the DOM, because i don't know how to register for unmounted here. I tried already vNode.props?.onVnodeUnmounted
but the vnode does not get unmounted. It's just the component which will be unmounted
I need somehow to register for the unmounted of the component. Anyone knows how to do this?
The unmount was not triggert for my component because there is no v-if on the main component which is getting mounted in the composable. I expose now a isVisible flag from all dialog components to trigger removing of the vnode.
const mountDialog = <T extends { new (...args: any[]): any }>(
component: T,
props: ExtractPropTypes<InstanceType<T>>
) => {
const container = document.createElement('div')
const vNode = h(component, props)
vNode.appContext = appContext
render(vNode, container)
if (vNode.component?.exposed?.isVisible === undefined) {
throw new Error(
'Dialog must expose isVisible otherwise unmount does not work!'
)
}
const stopWatcher = watch(vNode.component?.exposed?.isVisible, () => {
render(null, container)
document.body.removeChild(container)
stopWatcher()
})
document.body.appendChild(container)
}