0

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>
Marzz
  • 49
  • 6
  • 1
    What have you tried so far? Could you share a [mcve] with the relevant code, what you tried and what didn't work in that solution? – Sumurai8 May 01 '21 at 11:40
  • Have you tried adapting the solutions mentioned in the referenced SO question and only stopping the event propagation depending on your `allowClickOutside` variable? – Sebastian Richner May 01 '21 at 11:58
  • @Sebastian Richner: I updated the post but have no idea how to optionally prevent the event propogation inside a custom Vue directive; hence my question! – Marzz May 01 '21 at 12:28

0 Answers0