floating-vue
floating-vue copied to clipboard
Close nested VDropdown without closing parent programmatically
Hello! I would like to close a nested VDropdown inside another VDropdown.
I tried with the v-close-popper directive on the div node and it works. However, I would like to do some processing (async calls for example) before closing the popper so I can't use the directive as-is.
I also tried to use the hide method exposed by the #popper slot, I got the same result.
I also don't want to use :auto-hide="false" on the parent VDropdown because I want to autoclose when the click is outside
Here is a minimal example, when I click on Hello, the nested AND the parent VDropdown close.
<template>
<div class="example flex justify-center items-center gap-6">
<VDropdown placement="bottom-start">
<button class="border border-gray-300 rounded px-4 py-2">Click me</button>
<template #popper>
<VDropdown v-model:shown="open" placement="right-start">
<button class="rounded hover:bg-green-100 px-4 py-2">Option ></button>
<template #popper>
<div class="px-6 py-2" @click="onClick">Hello</div>
</template>
</VDropdown>
</template>
</VDropdown>
</div>
</template>
<script setup>
import { ref } from "vue";
const open = ref(false);
function onClick() {
// Some processing ...
open.value = false;
}
</script>
bump
Reproduction: https://stackblitz.com/edit/vitejs-vite-t58z89?file=src%2FApp.vue
Expected behavior: only the closest dropdown is closed when calling the hide method
Current behavior: the all dropdown hierarchy closes
Same here, really need to fix it!
zhaivoronok, kduvignau Very dirty hack, nothing seems to be broken (but it's not for sure)
https://github.com/Akryum/floating-vue/blob/main/packages/floating-vue/src/components/Popper.ts#L454
if (this.shownChildren.size > 0) {
- this.$_pendingHide = true
return
}
https://github.com/Akryum/floating-vue/blob/main/packages/floating-vue/src/components/Popper.ts#L477
- this.$_scheduleHide(event, skipDelay)
+ setTimeout(() => {
+ this.$_scheduleHide(event, skipDelay)
+ }, 0);
Thanks for providing your solution @or2e !
FYI, there is an official package for floating ui for Vue, you can find out here : https://www.npmjs.com/package/@floating-ui/vue
Hi was this fixed? @zhaivoronok @kduvignau @or2e
Solution:
<template>
<Dropdown :shown="open" @show="onShow" @hide="onHide">
<slot></slot>
<div slot="popper"></div>
</Dropdown>
</template>
<script>
import { Dropdown } from 'v-tooltip'
export default {
name: 'Popover',
components: {
Dropdown,
},
data() {
return {
autoHide_: this.autoHide,
isOpened: false,
}
},
watch: {
autoHide(newValue) {
this.autoHide_ = newValue
},
},
methods: {
setParentAutoHideToFalse() {
let parent = this.$parent
while (parent) {
if (parent.$el.classList.contains('v-popper') && parent.isOpened) {
parent.autoHide_ = false
if (parent.$el.parentNode === document.body) {
break
}
}
parent = parent.$parent
}
},
setParentAutoHideToTrue() {
let parent = this.$parent
while (parent) {
if (parent.$el.classList.contains('v-popper') && parent.isOpened) {
parent.autoHide_ = true
break
}
parent = parent.$parent
}
},
onShow() {
this.isOpened = true
setTimeout(() => this.setParentAutoHideToFalse(), 200)
},
onHide() {
this.isOpened = false
setTimeout(() => this.setParentAutoHideToTrue(), 100)
},
},
}
</script>
@ishaiavrahami No ( Updated the reproduction: https://stackblitz.com/edit/vitejs-vite-kfcze6?file=src%2FApp.vue
This is still not resolved after two years?