Detect click outside element
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
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/
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>
There are two packages available in the community for this task (both are maintained):
- https://github.com/simplesmiler/vue-clickaway
- https://github.com/ndelvalle/v-click-outside