Detect click outside an element in Vue.js

Vue components are isolated so anti-pattern is used to detect a click outside the element. You can set up a custom directive and use it to solve this issue.


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() }

})

In the template:

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

Some content

</div>

Use it in the component:

events: {

nameOfCustomEventToCall: function (event) {

// do something - probably hide the dropdown menu / modal etc.

}

}

Another way is to use @blur. It is easier than the above method and gives the same result.


<input @blur="hide"> where hide: function() { this.isActive = false; }


The first solution ie the custom directive works fine in vue.js 2.0 if used as shown below.


Vue.directive('click-outside', {

bind: function(el, binding, vnode) {

el.clickOutsideEvent = function (event) {

// here I check that click was outside the el and his childrens

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)

},

});

Lets see what are el, binding, vnod in the above code snippet.

El: The element to which the directive is bound to. This can be used to directly manipulate the DOM.

Binding: binding is an object containing the following properties.

Name- The name of the directive without v- prefix.

Value- The value passed to the directive

Oldvalue-The previous value . Available in update and componentUpdated.

Expression-The expression of the binding as a string

arg- the argument passed to the directive if any.

Modifiers- An object containing modifiers if any.

Vnode- the virtual node produced by Vue’s compiler.

OldVnode- The previous virtual node only available in the update and componentUpdated hooks.