Skip to content

Instantly share code, notes, and snippets.

@skunkworker
Created June 19, 2019 23:15
Show Gist options
  • Save skunkworker/ee6e45a9d1876104de3d11cb80e1ccc4 to your computer and use it in GitHub Desktop.
Save skunkworker/ee6e45a9d1876104de3d11cb80e1ccc4 to your computer and use it in GitHub Desktop.
Vue-closable directive (with fixes)
// imported from
// https://medium.com/@Taha_Shashtari/an-easy-way-to-detect-clicks-outside-an-element-in-vue-1b51d43ff634
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) => {
e.stopPropagation()
// 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(e.target)
}
}
})
// We check to see if the clicked element is not
// the dialog element and not excluded
if (!el.contains(e.target) && !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
vnode.context[handler]()
}
}
// 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