1

I have global directive to hide modal when user click out:

Vue.directive('click-outside', {
  bind(el, binding, vNode) {
    el.clickOutside = event => {      
      if (!(el == event.target || el.contains(event.target))) {
            vNode.context[binding.expression](event);
            event.stopPropagation();
        }
    }
    document.body.addEventListener('click', el.clickOutside)
  },
  unbind(el) {
    document.removeEventListener('click', el.clickOutside)
    el.clickOutside = null
  }
});

Next I have use this directive:

<img src="noti.png" id="1" v-click-outside="onClickOutside('notification')">

<img src="dots.png" id="2" v-click-outside="onClickOutside('profile')">

I have problem because I cant use this same directive on one component. Vue retururn me erro:

vNode.context[binding.expression] is not a function

I found this query, but the answer not help me. When add console.log to directive and click for example on first img directives will be done twice.

How I can detect (in directive) which img was clicked ?

michal
  • 1,534
  • 5
  • 28
  • 62
  • You are checking opposite action - which img isn't clicked. To catch img click event, use just v-on:click – Emīls Gulbis Jul 29 '19 at 21:40
  • Just an FYI, you don't need to do` el == event.target` and `el.contains(event.target)`, you can just use `contains()` as will return `true` for descendant of a given node including itself https://developer.mozilla.org/en-US/docs/Web/API/Node/contains. – Rwd Jul 29 '19 at 21:47

1 Answers1

0

The value you pass to custom directives will be evaluated straight away when the template is rendered. This is unlike v-on which has special behavior by the Vue template compiler which will automatically wrap it in a function.

I explain this in more detail in this answer.

I don't know if this will completely fix your problem, but at least you need to do something like this:

<img src="noti.png" id="1" v-click-outside="() => onClickOutside('notification')">
Decade Moon
  • 32,968
  • 8
  • 81
  • 101