Vuetify: 1.5.10
Last working version: 1.2.10
Vue: 2.6.10
Browsers: Chrome 71.0.3578.80
OS: Windows 10
Use v-menu with an item (@click.stop handler) that triggers a v-dialog to open.
Dialog appears, and menu auto-closes
1 - menu remains open when dialog is opened
2 - menu remains open after dialog is closed
When nesting the v-dialog inside v-menu, both 1 and 2 occur.
When v-dialog is outside v-menu the menu, only 1 occurs.
https://codesandbox.io/s/j3n1rl8x3w
Removing the .stop modifier...
In my application this nesting is happening across a few components, so the codesandbox is a contrived example.This kind of nesting is probably not the best architecture so I'm re-coding my application in any case.
I report this because: it used to work (vuetify 1.2.x); using the .stop modifier is not always working; and the documentation doesn't have anything about how vuetify components can/can't be nested.
If you want to have a dialog in the menu you can also use setTimeout https://codesandbox.io/s/r448jzw5lm
This has something to do with changes in microtasks in Vue 2.6, not sure if we can do something about it
This is simply a shortcoming of mixing nested activators. Not entirely sure on a path forward but it is something I'd like to make better.
After digging into this, I retract my previous statement. It actually has to do with this:
When the menu is closed, all of the children that depend on it are closed as well. In this case, dialog is a dependent of menu. If we did not do this, it would cause interaction issues with other components. Imagine a menu in a dialog, or a dialog in a drawer. If either the dialog or the drawer closes, you wouldn't want the existing menu or dialog lingering around.
The only solution for this that I can think of would involve adding a specific prop to enable this and I'm not entirely convinced that it should be added due to the above reasons.
Here is a workaround: https://codepen.io/johnjleider/pen/ZEzJyrQ?editors=1111
This will obviously break nested dependent interactions and I'm not sure how it would fair for your user-case. I'll leave this open for feedback but I don't believe this is a bug.
A little bit annoying issue, but you can wrap it in your own component for reuse. Works same as normal VDialog (using activator slot), additionally it serves close method on default slot. Written in typescript, but can be modified to work with normal JS.
EDIT: Created using: Vue 2.6.10 && Vuetify 2.2.6
<template>
<VDialog v-model="isShown" v-bind="$attrs" v-on="$listeners">
<template #activator="{ on }">
<slot name="activator" v-bind="{ on: getSafeOnHandler(on) }" />
</template>
<slot v-bind="{ close }" />
</VDialog>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'BaseInMenuDialog',
data: () => ({
isShown: false,
}),
methods: {
// @see: https://github.com/vuetifyjs/vuetify/issues/7021
getSafeOnHandler({ click }: { click: Function }): { click: Function } {
return {
click(event: Event) {
return setTimeout(() => click(event), 0)
},
}
},
close(): void {
this.isShown = false
},
},
})
</script>
Most helpful comment
This is simply a shortcoming of mixing nested activators. Not entirely sure on a path forward but it is something I'd like to make better.