Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Vue-closable directive (with fixes)
// imported from
import Vue from 'vue'
// This variable will hold the reference to
// document's click handler
let handleOutsideClick
Vue.directive('closable', {
bind (el, binding, vnode) {
// Here's the click/touchstart handler
// (it is registered below)
handleOutsideClick = (e) => {
// Get the handler method name and the exclude array
// from the object used in v-closable
const { handler, exclude } = binding.value
// This variable indicates if the clicked element is excluded
let clickedOnExcludedEl = false
exclude.forEach(refName => {
// We only run this code if we haven't detected
// any excluded element yet
if (!clickedOnExcludedEl) {
// Get the element using the reference name
const excludedEl = vnode.context.$refs[refName]
// this line was added because if you v-if/else hide an element then it would throw an error about excludedEl being undefined.
if (excludedEl) {
// See if this excluded element
// is the same element the user just clicked on
clickedOnExcludedEl = excludedEl.contains(
// We check to see if the clicked element is not
// the dialog element and not excluded
if (!el.contains( && !clickedOnExcludedEl) {
// If the clicked element is outside the dialog
// and not the button, then call the outside-click handler
// from the same component this directive is used in
// Register click/touchstart event listeners on the whole page
document.addEventListener('click', handleOutsideClick)
document.addEventListener('touchstart', handleOutsideClick)
unbind () {
// If the element that has v-closable is removed, then
// unbind click/touchstart listeners from the whole page
document.removeEventListener('click', handleOutsideClick)
document.removeEventListener('touchstart', handleOutsideClick)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment