1

Vue JS 2.6.10

I have read a variety of SO posts about how to create a custom directive so that you can detect a click outside of a popup menu so you can close it. I can't quite get it to work because I have a button that opens the menu and clicking it fires the "close" behavior.

Here's my main view Logbook.vue that has the button that opens the menu: enter image description here

// --- Logbook.vue ---
<script>
export default {
  name: 'Logbook',
  components:{
    Years
  },
  methods:{
    clickYears: function(){
      this.$refs.Years.show = true
    }
  }
}
</script>
<template>
  <div id="current-year">
    <a href="#year" ref="yearButton" v-on:click.prevent="clickYears">{{ currentYear }}</a>
    <Years ref="Years" v-on:selectYear="yearSelected" />
  </div>
</template>

Here is the menu component Years.vue that opens when you click the button: enter image description here

//--- Years.vue ---
<script>
import Vue from 'vue'

//Custom directive to handle clicks outside of this component
Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    window.event = function (event) {
      if (!(el == event.target || el.contains(event.target))) {
        vnode.context[binding.expression](event)
      }
    };
    document.body.addEventListener('click', window.event)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', window.event)
  }
})

export default{
  name: 'Years',
  data() {
    return {
      show: false
    }
  },
  methods:{
    close: function(){
      this.show = false
    }
  }
}
</script>

<template>
  <div id="years" v-show="show" v-click-outside="close">
  <!-- Years listed here... -->
  </div>
</template>

The close method is firing appropriately when I click outside of the Years component, but the problem is that I can't ever open the Years menu to begin with because clicking the button also fires the close behavior because it's also outside of the Years component.

Has anyone overcome this problem? Any ideas?

Clifton Labrum
  • 13,053
  • 9
  • 65
  • 128

1 Answers1

5

try this

...
methods:{
  clickYears: function(event){
    this.$refs.Years.show = true
    event.stopPropagation();
  }
}
...
Milad Dehghan
  • 307
  • 3
  • 16
  • 1
    You, my friend, are a genius. So I guess this stops the event from propagating all they way up to the `close` event listener that's on the `body` element. Very nice. Thank you! – Clifton Labrum May 20 '19 at 23:29
  • Actually it prevents propagating close event to the btn. see more at https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation – Milad Dehghan May 22 '19 at 10:37