Click-Outside Directive
The v-click-outside
directive is used to detect clicks outside of an element. It is useful for closing dropdowns, modals, and other components that require a click outside to close.
Usage
html
<div v-click-outside="onClickOutside">
<!-- Your content here -->
</div>
View Code
vue
<template>
<button
@click="toggleDropdown"
class="px-2 py-1 w-full bg-blue-500 text-white rounded-lg max-w-xs"
type="button"
>
Dropdown button
</button>
<!-- Dropdown menu -->
<div
v-if="showDropdown"
v-click-outside="closeDropdown"
class="w-full max-w-xs z-10 bg-white divide-y divide-zinc-100 rounded-lg border dark:border-zinc-700 dark:bg-zinc-700"
>
<div class="py-2 text-sm text-zinc-700 dark:text-zinc-200 list-none">
<li
class="block px-4 py-2 hover:bg-zinc-100 dark:hover:bg-zinc-600 dark:hover:text-white"
>
Dashboard
</li>
<li
class="block px-4 py-2 hover:bg-zinc-100 dark:hover:bg-zinc-600 dark:hover:text-white"
>
Settings
</li>
<li
class="block px-4 py-2 hover:bg-zinc-100 dark:hover:bg-zinc-600 dark:hover:text-white"
>
Earnings
</li>
<li
class="block px-4 py-2 hover:bg-zinc-100 dark:hover:bg-zinc-600 dark:hover:text-white"
>
Sign out
</li>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const showDropdown = ref(false);
const toggleDropdown = () => (showDropdown.value = !showDropdown.value);
const closeDropdown = () => (showDropdown.value = false);
</script>
Arguments
The v-click-outside
directive does not accept any arguments.
Modifiers
The v-click-outside
directive does not accept any modifiers.
Source Code
js
export const vClickOutside = {
beforeMount(el, binding) {
el.clickOutsideEvent = function (event) {
const isTouch = event.type === "touchstart";
const isClickOutside = !(
el === event.target || el.contains(event.target)
);
if (isTouch || isClickOutside) {
if (binding.value) {
let shouldTrigger = true;
// Check for modifiers
if (binding.modifiers) {
if (binding.modifiers.enter && !event.key === "Enter") {
shouldTrigger = false;
}
// Add more modifiers as needed
}
// Check for a custom filter function
if (typeof binding.value === "function" && !binding.value(event)) {
shouldTrigger = false;
}
if (shouldTrigger) {
binding.value(event);
}
}
}
};
// Use capturing phase to handle events before they reach other elements
document.addEventListener("click", el.clickOutsideEvent, true);
document.addEventListener("touchstart", el.clickOutsideEvent, true);
},
unmounted(el) {
document.removeEventListener("click", el.clickOutsideEvent, true);
document.removeEventListener("touchstart", el.clickOutsideEvent, true);
},
};