I found several questions about detecting a click outside elements in Vue JS, including posts about the v-click-outside directive and user-written custom directives. The most informative post with lots of code was Detect click outside element, from which I copied Pablo Huet Carrasco's code as shown below.
However, I have a slightly different problem. That is, until a local data boolean (e.g. "allowClickOutside") becomes true, I need to prevent all clicks outside of the element. Only when "allowClickOutside" is true the .prevent.stop modification should no longer be in place and all clicks outside the element should be allowed. How can this be implemented in the following Vue (3) directive?
Vue 3 Directive with event propagation:
const clickOutside = {
beforeMount: (el, binding) => {
el.eventSetDrag = () => {
el.setAttribute("data-dragging", "yes");
};
el.eventClearDrag = () => {
el.removeAttribute("data-dragging");
};
el.eventOnClick = event => {
const dragging = el.getAttribute("data-dragging");
// Check that the click was outside the el and its children, and wasn't a drag
if (!(el == event.target || el.contains(event.target)) && !dragging) {
// call method provided in attribute value
binding.value(event);
}
};
document.addEventListener("touchstart", el.eventClearDrag);
document.addEventListener("touchmove", el.eventSetDrag);
document.addEventListener("click", el.eventOnClick);
document.addEventListener("touchend", el.eventOnClick);
},
unmounted: el => {
document.removeEventListener("touchstart", el.eventClearDrag);
document.removeEventListener("touchmove", el.eventSetDrag);
document.removeEventListener("click", el.eventOnClick);
document.removeEventListener("touchend", el.eventOnClick);
el.removeAttribute("data-dragging");
},
}
createApp(App)
.directive("click-outside", clickOutside)
.mount("#app");
How to use:
<template>
<div v-click-outside="myMethod">
<div class="handle" @click="doAnotherThing($event)">
<div>Any content</div>
</div>
</div>
</template>