Created
June 19, 2019 23:15
-
-
Save skunkworker/ee6e45a9d1876104de3d11cb80e1ccc4 to your computer and use it in GitHub Desktop.
Vue-closable directive (with fixes)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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