Detect click outside element

Javascriptvue.js

Javascript Problem Overview


How can I detect a click outside my element? I'm using Vue.js so it's gonna be outside my templates element. I know how to do it in Vanilla JS, but I'm not sure if there's a more proper way to do it, when I'm using Vue.js?

This is the solution for Vanilla JS: https://stackoverflow.com/questions/18893144/javascript-detect-click-event-outside-of-div

I guess I can use a better way to access the element?

Javascript Solutions


Solution 1 - Javascript

There is the solution I used, which is based on Linus Borg answer and works fine with vue.js 2.0.

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    el.clickOutsideEvent = function (event) {
      // here I check that click was outside the el and his children
      if (!(el == event.target || el.contains(event.target))) {
        // and if it did, call method provided in attribute value
        vnode.context[binding.expression](event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
});

You bind to it using v-click-outside:

<div v-click-outside="doStuff">

Here's a small demo

You can find some more info about custom directives and what el, binding, vnode means in https://vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments

Solution 2 - Javascript

Keep in attention that this solution only works with Vue 1.

Can be solved nicely by setting up a custom directive once:

Vue.directive('click-outside', {
  bind () {
      this.event = event => this.vm.$emit(this.expression, event)
      this.el.addEventListener('click', this.stopProp)
      document.body.addEventListener('click', this.event)
  },   
  unbind() {
    this.el.removeEventListener('click', this.stopProp)
    document.body.removeEventListener('click', this.event)
  },

  stopProp(event) { event.stopPropagation() }
})

Usage:

<div v-click-outside="nameOfCustomEventToCall">
  Some content
</div>

In the component:

events: {
  nameOfCustomEventToCall: function (event) {
    // do something - probably hide the dropdown menu / modal etc.
  }
}

Working Demo on JSFiddle with additional info about caveats:

https://jsfiddle.net/Linusborg/yzm8t8jq/

Solution 3 - Javascript

Add tabindex attribute to your component so that it can be focused and do the following:

<template>
	<div
		@focus="handleFocus"
		@focusout="handleFocusOut"
		tabindex="0"
	>
      SOME CONTENT HERE
	</div>
</template>

<script>
export default {	
	methods: {
		handleFocus() {
			// do something here
		},
		handleFocusOut() {
			// do something here
		}
	}
}
</script>

Solution 4 - Javascript

There are two packages available in the community for this task (both are maintained):

Solution 5 - Javascript

For Vue 3:

This answer is based on MadisonTrash's great answer above but updated to use new Vue 3 syntax.

Vue 3 now uses beforeMount instead of bind, and unmounted instead of unbind (src).

const clickOutside = {
  beforeMount: (el, binding) => {
    el.clickOutsideEvent = event => {
      // here I check that click was outside the el and his children
      if (!(el == event.target || el.contains(event.target))) {
        // and if it did, call method provided in attribute value
        binding.value();
      }
    };
    document.addEventListener("click", el.clickOutsideEvent);
  },
  unmounted: el => {
    document.removeEventListener("click", el.clickOutsideEvent);
  },
};

createApp(App)
  .directive("click-outside", clickOutside)
  .mount("#app");

Solution 6 - Javascript

I did it a slightly different way using a function within created().

  created() {
      window.addEventListener('click', (e) => {
        if (!this.$el.contains(e.target)){
          this.showMobileNav = false
        }
      })
  },

This way, if someone clicks outside of the element, then in my case, the mobile nav is hidden.

Solution 7 - Javascript

This Worked for me with Vue.js 2.5.2 :

/**
 * Call a function when a click is detected outside of the
 * current DOM node ( AND its children )
 *
 * Example :
 *
 * <template>
 *   <div v-click-outside="onClickOutside">Hello</div>
 * </template>
 *
 * <script>
 * import clickOutside from '../../../../directives/clickOutside'
 * export default {
 *   directives: {
 *     clickOutside
 *   },
 *   data () {
 *     return {
         showDatePicker: false
 *     }
 *   },
 *   methods: {
 *     onClickOutside (event) {
 *       this.showDatePicker = false
 *     }
 *   }
 * }
 * </script>
 */
export default {
  bind: function (el, binding, vNode) {
    el.__vueClickOutside__ = event => {
      if (!el.contains(event.target)) {
        // call method provided in v-click-outside value
        vNode.context[binding.expression](event)
        event.stopPropagation()
      }
    }
    document.body.addEventListener('click', el.__vueClickOutside__)
  },
  unbind: function (el, binding, vNode) {
    // Remove Event Listeners
    document.body.removeEventListener('click', el.__vueClickOutside__)
    el.__vueClickOutside__ = null
  }
}

Solution 8 - Javascript

I have combined all answers (including a line from vue-clickaway) and came up with this solution that works for me:

Vue.directive('click-outside', {
    bind(el, binding, vnode) {
        var vm = vnode.context;
        var callback = binding.value;

        el.clickOutsideEvent = function (event) {
            if (!(el == event.target || el.contains(event.target))) {
                return callback.call(vm, event);
            }
        };
        document.body.addEventListener('click', el.clickOutsideEvent);
    },
    unbind(el) {
        document.body.removeEventListener('click', el.clickOutsideEvent);
    }
});

Use in component:

<li v-click-outside="closeSearch">
  <!-- your component here -->
</li>

Solution 9 - Javascript

If you're specifically looking for a click outside the element but still within the parent, you can use

<div class="parent" @click.self="onParentClick">
  <div class="child"></div>
</div>

I use this for modals.

Solution 10 - Javascript

Vue 3 has breaking changes in directives, all of Vue 3, Here's the snippet. For information please go through this link

<div v-click-outside="methodToInvoke"></div>

click-outside.js

export default {
  beforeMount: function (el, binding, vnode) {
    binding.event = function (event) {
      if (!(el === event.target || el.contains(event.target))) {
        if (binding.value instanceof Function) {
          binding.value(event)
        }
      }
    }
    document.body.addEventListener('click', binding.event)
  },
  unmounted: function (el, binding, vnode) {
    document.body.removeEventListener('click', binding.event)
  }
}

and In main.js add the following

// Directives
import ClickOutside from './click-outside'

createApp(App)
 .directive('click-outside', ClickOutside)
 .use(IfAnyModules)
 .mount('#app')

Solution 11 - Javascript

I have updated MadisonTrash's answer to support Mobile Safari (which does not have click event, touchend must be used instead). This also incorporates a check so that the event isn't triggered by dragging on mobile devices.

Vue.directive('click-outside', {
    bind: function (el, binding, vnode) {
        el.eventSetDrag = function () {
            el.setAttribute('data-dragging', 'yes');
        }
        el.eventClearDrag = function () {
            el.removeAttribute('data-dragging');
        }
        el.eventOnClick = function (event) {
            var 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
                vnode.context[binding.expression](event);
            }
        };
        document.addEventListener('touchstart', el.eventClearDrag);
        document.addEventListener('touchmove', el.eventSetDrag);
        document.addEventListener('click', el.eventOnClick);
        document.addEventListener('touchend', el.eventOnClick);
    }, unbind: function (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');
    },
});

Solution 12 - Javascript

export default {
  bind: function (el, binding, vNode) {
    // Provided expression must evaluate to a function.
    if (typeof binding.value !== 'function') {
      const compName = vNode.context.name
      let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`
      if (compName) { warn += `Found in component '${compName}'` }

      console.warn(warn)
    }
    // Define Handler and cache it on the element
    const bubble = binding.modifiers.bubble
    const handler = (e) => {
      if (bubble || (!el.contains(e.target) && el !== e.target)) {
        binding.value(e)
      }
    }
    el.__vueClickOutside__ = handler

    // add Event Listeners
    document.addEventListener('click', handler)
  },

  unbind: function (el, binding) {
    // Remove Event Listeners
    document.removeEventListener('click', el.__vueClickOutside__)
    el.__vueClickOutside__ = null

  }
}

Solution 13 - Javascript

Complete case for vue 3

This is a complete solution based on MadisonTrash answer, and benrwb and fredrivett tweaks for safari compatibility and vue 3 api changes.

Edit:

The solution proposed below is still useful, and the how to use is still valid, but I changed it to use document.elementsFromPoint instead of event.contains because it doesn't recognise as children some elements like the <path> tags inside svgs. So the right directive is this one:

export default {
	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
			console.log(document.elementsFromPoint(event.clientX, event.clientY))
			if (!document.elementsFromPoint(event.clientX, event.clientY).includes(el) && !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");
	},
};

Old answer:

Directive
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");

This solution watch the element and the element's children of the component where the directive is applied to check if the event.target element is also a child. If that's the case it will not trigger, because it's inside the component.

How to use it

You only have to use as any directive, with a method reference to handle the trigger:

<template>
    <div v-click-outside="myMethod">
        <div class="handle" @click="doAnotherThing($event)">
            <div>Any content</div>
        </div>
    </div>
</template>

Solution 14 - Javascript

I create a div at the end of the body like that:

<div v-if="isPopup" class="outside" v-on:click="away()"></div>

Where .outside is :

.outside {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0px;
  left: 0px;
}

And away() is a method in Vue instance :

away() {
 this.isPopup = false;
}

Solution 15 - Javascript

I use this code:

show-hide button

 <a @click.stop="visualSwitch()"> show hide </a>

show-hide element

<div class="dialog-popup" v-if="visualState" @click.stop=""></div>

script

data () { return {
    visualState: false,
}},
methods: {
    visualSwitch() {
        this.visualState = !this.visualState;
        if (this.visualState)
            document.addEventListener('click', this.visualState);
        else
            document.removeEventListener('click', this.visualState);
    },
},

Update: remove watch; add stop propagation

Solution 16 - Javascript

I hate additional functions so... here is an awesome vue solution without an additional vue methods, only var

  1. create html element, set controls and directive
    <p @click="popup = !popup" v-out="popup">
    
    <div v-if="popup">
       My awesome popup
    </div>
  1. create a var in data like
data:{
   popup: false,
}
  1. add vue directive. its
Vue.directive('out', {

    bind: function (el, binding, vNode) {
        const handler = (e) => {
            if (!el.contains(e.target) && el !== e.target) {
                //and here is you toggle var. thats it
                vNode.context[binding.expression] = false
            }
        }
        el.out = handler
        document.addEventListener('click', handler)
    },

    unbind: function (el, binding) {
        document.removeEventListener('click', el.out)
        el.out = null
    }
})

Solution 17 - Javascript

You can register two event listeners for click event like this

document.getElementById("some-area")
        .addEventListener("click", function(e){
        alert("You clicked on the area!");
        e.stopPropagation();// this will stop propagation of this event to upper level
     }
);

document.body.addEventListener("click", 
   function(e) {
           alert("You clicked outside the area!");
         }
);

Solution 18 - Javascript

There are already many answers to this question, and most of them are based on the similar custom directive idea. The problem with this approach is that one have to pass a method function to the directive, and cannot directly write code as in other events.

I created a new package vue-on-clickout that is different. Check it out at:

It allows one to write v-on:clickout just like any other events. For example, you can write

<div v-on:clickout="myField=value" v-on:click="myField=otherValue">...</div>

and it works.

Update

vue-on-clickout now supports Vue 3!

Update 2

vue-on-clickout is now replaced by a new package Clickout-Event which works for any front-end framework (or vanilla)!

Solution 19 - Javascript

You can emit custom native javascript event from a directive. Create a directive that dispatches an event from the node, using node.dispatchEvent

let handleOutsideClick;
Vue.directive('out-click', {
    bind (el, binding, vnode) {

        handleOutsideClick = (e) => {
            e.stopPropagation()
            const handler = binding.value
            
            if (el.contains(e.target)) {
                el.dispatchEvent(new Event('out-click')) <-- HERE
            }
        }

        document.addEventListener('click', handleOutsideClick)
        document.addEventListener('touchstart', handleOutsideClick)
    },
    unbind () {
        document.removeEventListener('click', handleOutsideClick)
        document.removeEventListener('touchstart', handleOutsideClick)
    }
})

Which can be used like this

h3( v-out-click @click="$emit('show')" @out-click="$emit('hide')" )

Solution 20 - Javascript

If you have a component with multiple elements inside of the root element you can use this It just works™ solution with a boolean.

<template>
  <div @click="clickInside"></div>
<template>
<script>
export default {
  name: "MyComponent",
  methods: {
    clickInside() {
      this.inside = true;
      setTimeout(() => (this.inside = false), 0);
    },
    clickOutside() {
      if (this.inside) return;
      // handle outside state from here
    }
  },
  created() {
    this.__handlerRef__ = this.clickOutside.bind(this);
    document.body.addEventListener("click", this.__handlerRef__);
  },
  destroyed() {
    document.body.removeEventListener("click", this.__handlerRef__);
  },
};
</script>

Solution 21 - Javascript

  <button 
    class="dropdown"
    @click.prevent="toggle"
    ref="toggle"
    :class="{'is-active': isActiveEl}"
  >
    Click me
  </button>

  data() {
   return {
     isActiveEl: false
   }
  }, 
  created() {
    window.addEventListener('click', this.close);
  },
  beforeDestroy() {
    window.removeEventListener('click', this.close);
  },
  methods: {
    toggle: function() {
      this.isActiveEl = !this.isActiveEl;
    },
    close(e) {
      if (!this.$refs.toggle.contains(e.target)) {
        this.isActiveEl = false;
      }
    },
  },

Solution 22 - Javascript

The short answer: This should be done with Custom Directives.

There are a lot of great answers here that also say this, but most of the answers I have seen break down when you start using outside-click extensively (especially layered or with multiple excludes). I have written an article on medium talking about the nuances of Custom Directives and specifically implementation of this one. It may not cover all edge cases but it has covered everything I have thought up.

This will account for multiple bindings, multiple levels of other element exclusions and allow your handler to only manage the "business logic".

Here's the code for at least the definition portion of it, check out the article for full explanation.

var handleOutsideClick={}
const OutsideClick = {
  // this directive is run on the bind and unbind hooks
  bind (el, binding, vnode) {
    // Define the function to be called on click, filter the excludes and call the handler
    handleOutsideClick[el.id] = e => {
      e.stopPropagation()
      // extract the handler and exclude from the binding value
      const { handler, exclude } = binding.value
      // set variable to keep track of if the clicked element is in the exclude list
      let clickedOnExcludedEl = false
      // if the target element has no classes, it won't be in the exclude list skip the check
      if (e.target._prevClass !== undefined) {
        // for each exclude name check if it matches any of the target element's classes
        for (const className of exclude) {
          clickedOnExcludedEl = e.target._prevClass.includes(className)
          if (clickedOnExcludedEl) {
            break // once we have found one match, stop looking
          }
        }
      }
      // don't call the handler if our directive element contains the target element
      // or if the element was in the exclude list
      if (!(el.contains(e.target) || clickedOnExcludedEl)) {
        handler()
      }
    }
    // Register our outsideClick handler on the click/touchstart listeners
    document.addEventListener('click', handleOutsideClick[el.id])
    document.addEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = e => {
      //this is an option but may not work right with multiple handlers
      if (e.keyCode === 27) {
        // TODO: there are minor issues when escape is clicked right after open keeping the old target
        handleOutsideClick[el.id](e)
      }
    }
  },
  unbind () {
    // If the element that has v-outside-click is removed, unbind it from listeners
    document.removeEventListener('click', handleOutsideClick[el.id])
    document.removeEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = null //Note that this may not work with multiple listeners
  }
}
export default OutsideClick

Solution 23 - Javascript

For those using Vue 3.

Vue3 has changed the syntax for Directive Hooks:

  • Bind -> beforeMount
  • Unbind -> unmounted

To detect a click outside an element in Vue 3:

> click-outside.js

export default function directive(app) {
  // you can name the directive whatever you want. -> click-outside
  app.directive('click-outside', {
    beforeMount(el, binding) {
      el.clickOutsideEvent = (evt) => {
        evt.stopPropagation();
        if (!(el === evt.target || el.contains(evt.target))) {
          binding.value(evt, el);
        }
      };
      window.requestAnimationFrame(() => {
        document.addEventListener("click", el.clickOutsideEvent);
      });
    },
    unmounted(el) {
      document.removeEventListener("click", el.clickOutsideEvent);
    },
  })
}

Register directive:

> main.js

import { createApp } from "vue";
import App from "./App.vue";

// Import your directive, in order to register it.
import clickOutside from "./directives/click-outside.js"

createApp(App).use(clickOutside).mount("#app");

Usage:

<template>
  <div class="dropdown" v-click-outside="() => hideDropdown()"></div>
</template>
<script setup>
  function hideDropdown() {
    console.log("close dropdown")
  }
</script>

### OR 

<script>
  methods: {
    hideDropdown() {
      console.log("close dropdown")
    }
  }
</script> 

Solution 24 - Javascript

Frequently people want to know if user leave root component (works with any level components)

Vue({
  data: {},
  methods: {
    unfocused : function() {
      alert('good bye');
    }
  }
})

<template>
  <div tabindex="1" @blur="unfocused">Content inside</div>
</template>

Solution 25 - Javascript

Just if anyone is looking how to hide modal when clicking outside the modal. Since modal usually has its wrapper with class of modal-wrap or anything you named it, you can put @click="closeModal" on the wrapper. Using https://vuejs.org/v2/guide/events.html#Method-Event-Handlers">event handling stated in vuejs documentation, you can check if the clicked target is either on the wrapper or on the modal.

methods: {
  closeModal(e) {
    this.event = function(event) {
      if (event.target.className == 'modal-wrap') {
        // close modal here
        this.$store.commit("catalog/hideModal");
        document.body.removeEventListener("click", this.event);
      }
    }.bind(this);
    document.body.addEventListener("click", this.event);
  },
}

<div class="modal-wrap" @click="closeModal">
  <div class="modal">
    ...
  </div>
<div>

Solution 26 - Javascript

I am using this package : https://www.npmjs.com/package/vue-click-outside

It works fine for me

HTML :

<div class="__card-content" v-click-outside="hide" v-if="cardContentVisible">
    <div class="card-header">
        <input class="subject-input" placeholder="Subject" name=""/>
    </div>
    <div class="card-body">
        <textarea class="conversation-textarea" placeholder="Start a conversation"></textarea>
    </div>
</div>

My script codes :

import ClickOutside from 'vue-click-outside'
export default
{
    data(){
        return {
            cardContentVisible:false
        }
    },
    created()
    {
    },
    methods:
        {
            openCardContent()
            {
                this.cardContentVisible = true;
            }, hide () {
            this.cardContentVisible = false
                }
        },
    directives: {
            ClickOutside
    }
}

Solution 27 - Javascript

@Denis Danilenko solutions works for me, here's what I did: By the way I'm using VueJS CLI3 and NuxtJS here and with Bootstrap4, but it will work on VueJS without NuxtJS also:

<div
    class="dropdown ml-auto"
    :class="showDropdown ? null : 'show'">
    <a 
        href="#" 
        class="nav-link" 
        role="button" 
        id="dropdownMenuLink" 
        data-toggle="dropdown" 
        aria-haspopup="true" 
        aria-expanded="false"
        @click="showDropdown = !showDropdown"
        @blur="unfocused">
        <i class="fas fa-bars"></i>
    </a>
    <div 
        class="dropdown-menu dropdown-menu-right" 
        aria-labelledby="dropdownMenuLink"
        :class="showDropdown ? null : 'show'">
        <nuxt-link class="dropdown-item" to="/contact">Contact</nuxt-link>
        <nuxt-link class="dropdown-item" to="/faq">FAQ</nuxt-link>
    </div>
</div>
export default {
    data() {
        return {
            showDropdown: true
        }
    },
    methods: {
    unfocused() {
        this.showDropdown = !this.showDropdown;
    }
  }
}

Solution 28 - Javascript

Use this package vue-click-outside

It's simple and reliable, currently used by many other packages. You can also reduce your javascript bundle size by calling the package only in the required components (see example below).

npm install vue-click-outside

Usage :
<template>
  <div>
    <div v-click-outside="hide" @click="toggle">Toggle</div>
    <div v-show="opened">Popup item</div>
  </div>
</template>
 
<script>
import ClickOutside from 'vue-click-outside'
 
export default {
  data () {
    return {
      opened: false
    }
  },
 
  methods: {
    toggle () {
      this.opened = true
    },
 
    hide () {
      this.opened = false
    }
  },
 
  mounted () {
    // prevent click outside event with popupItem.
    this.popupItem = this.$el
  },
 
  // do not forget this section
  directives: {
    ClickOutside
  }
}
</script>

Solution 29 - Javascript

Don't reinvent the wheel, use this package v-click-outside

Solution 30 - Javascript

You can create new component which handle outside click

Vue.component('click-outside', {
  created: function () {
    document.body.addEventListener('click', (e) => {
       if (!this.$el.contains(e.target)) {
            this.$emit('clickOutside');
           
        })
  },
  template: `
    <template>
        <div>
            <slot/>
        </div>
    </template>
`
})

And use this component:

<template>
    <click-outside @clickOutside="console.log('Click outside Worked!')">
      <div> Your code...</div>
    </click-outside>
</template>

Solution 31 - Javascript

I'm not sure if someone will ever see this answer but here it is. The idea here is to simply detect if any click was done outside the element itself.

I first start by giving an id to the main div of my "dropdown".

<template>
  <div class="relative" id="dropdown">
    <div @click="openDropdown = !openDropdown" class="cursor-pointer">
      <slot name="trigger" />
    </div>

    <div
      class="absolute mt-2 w-48 origin-top-right right-0 text-red  bg-tertiary text-sm text-black"
      v-show="openDropdown"
      @click="openDropdown = false"
    >
      <slot name="content" />
    </div>
  </div>
</template>

And then I just loop thru the path of the mouse event and see if the div with my id "dropdown" is there. If it is, then we good, if it is no, then we close the dropdown.

<script>
export default {
  data() {
    return {
      openDropdown: false,
    };
  },
  created() {
    document.addEventListener("click", (e) => {
      let me = false;
      for (let index = 0; index < e.path.length; index++) {
        const element = e.path[index];

        if (element.id == "dropdown") {
          me = true;
          return;
        }
      }

      if (!me) this.openDropdown = false;
    });
  }
};
</script>

I'm pretty sure this can bring performance issues if you have many nested elements, but I found this as the most lazy-friendly way of doing it.

Solution 32 - Javascript

I have a solution for handling toggle dropdown menu:

export default {
data() {
  return {
    dropdownOpen: false,
  }
},
methods: {
      showDropdown() {
        console.log('clicked...')
        this.dropdownOpen = !this.dropdownOpen
        // this will control show or hide the menu
        $(document).one('click.status', (e)=> {
          this.dropdownOpen = false
        })
      },
}

Solution 33 - Javascript

Now you should use the vue-click-outside plugin for this.

  1. you can run an event when you click outside that's div.

    NPM Plugin: https://www.npmjs.com/package/v-click-outside

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser6102188View Question on Stackoverflow
Solution 1 - JavascriptMadisonTrashView Answer on Stackoverflow
Solution 2 - JavascriptLinus BorgView Answer on Stackoverflow
Solution 3 - JavascriptG'ofur NView Answer on Stackoverflow
Solution 4 - JavascriptJulien Le CoupanecView Answer on Stackoverflow
Solution 5 - JavascriptfredrivettView Answer on Stackoverflow
Solution 6 - JavascriptBrad AhrensView Answer on Stackoverflow
Solution 7 - Javascriptyann_yinnView Answer on Stackoverflow
Solution 8 - JavascriptBogdanGView Answer on Stackoverflow
Solution 9 - JavascriptAndres HolguinView Answer on Stackoverflow
Solution 10 - JavascriptNarenView Answer on Stackoverflow
Solution 11 - JavascriptbenrwbView Answer on Stackoverflow
Solution 12 - Javascriptxiaoyu2erView Answer on Stackoverflow
Solution 13 - JavascriptPablo Huet CarrascoView Answer on Stackoverflow
Solution 14 - JavascriptArnaud LiDzView Answer on Stackoverflow
Solution 15 - JavascriptPax ExterminatusView Answer on Stackoverflow
Solution 16 - JavascriptMartin PrestoneView Answer on Stackoverflow
Solution 17 - JavascriptsaravanakumarView Answer on Stackoverflow
Solution 18 - JavascriptMu-Tsun TsaiView Answer on Stackoverflow
Solution 19 - JavascriptPedro TorchioView Answer on Stackoverflow
Solution 20 - JavascriptA1rPunView Answer on Stackoverflow
Solution 21 - JavascriptDmytro LishtvanView Answer on Stackoverflow
Solution 22 - JavascriptMarcus SmithView Answer on Stackoverflow
Solution 23 - JavascriptMartin SeydoView Answer on Stackoverflow
Solution 24 - JavascriptDenis DanilenkoView Answer on Stackoverflow
Solution 25 - JavascriptjediView Answer on Stackoverflow
Solution 26 - JavascriptMurad ShukurluView Answer on Stackoverflow
Solution 27 - JavascriptalfieindesignsView Answer on Stackoverflow
Solution 28 - JavascriptSmit PatelView Answer on Stackoverflow
Solution 29 - Javascriptsnehanshu.jsView Answer on Stackoverflow
Solution 30 - JavascriptDictator47View Answer on Stackoverflow
Solution 31 - JavascriptMoncef Ben SlimaneView Answer on Stackoverflow
Solution 32 - JavascriptNicolas S.XuView Answer on Stackoverflow
Solution 33 - JavascriptSandesh MankarView Answer on Stackoverflow