0

I have this Vue code:

export default {
   data: function() {
     return {
       'showPopup': false
     }
   },
   components: {
     'search-bar': SearchBarComponent,
   },
   mounted: function() {
     $(this.$el).foundation();
   },
   updated: function() {
     $(this.$el).foundation();
   },
   methods: {
     clickOutsidePopup: function(event) {
       console.log(event);
     }
   },
   directives: {
     clickoutside: {
       bind (el) {
         el.event = event => el.vm.$emit(el.expression, event)
         el.addEventListener('click', el.stopProp)
         document.body.addEventListener('click', event)
       },   
       unbind(el) {
         el.removeEventListener('click', el.stopProp)
         document.body.removeEventListener('click', el.event)
       },

       stopProp(event) { event.stopPropagation() }
     }
   }
 } 

And inside the template I have this:

<div class="small-screen popup-container">
   <div class="popup" v-show="showPopup" v-clickoutside="clickOutsidePopup">
     <search-bar />
   </div>
 </div>

which will be shown/hidden if we click on this:

<a href="#"> <span @click="showPopup = !showPopup">&#128269;</span></a>

My problem is that my directive does not execute clickOutsidePopup. When I click outside of my element? I was inspired by this: Detect click outside element

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • There's a working example in the linked SO post, why are you not using it? – Bennett Dams Nov 09 '18 at 14:03
  • It involves a global directive. I intend to do this on component level. – Lajos Arpad Nov 09 '18 at 14:06
  • 1
    I recreated the example with a component directive and it works absolutely fine: https://jsfiddle.net/fj94mkpe/ The difference between your code and the example is the usage of the event as function parameter at the directive. – Bennett Dams Nov 09 '18 at 14:13
  • @BennettDams in the meantime I managed to make it work as well, see the edit on the question. Now the problem is that in mobile browsers the search button works (shows/hides the bar), but clicking outside the bar does not fire the event. – Lajos Arpad Nov 09 '18 at 14:17
  • @BennettDams my new problem is not related to my original question and your code is more-or-less equivalent to the solution I have reached independently from you. If you convert your comment into an answer, I will accept it. – Lajos Arpad Nov 09 '18 at 14:28

1 Answers1

0

I managed to make it work with this directive code:

  directives: {
    clickoutside: {
      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)
      },
    } 
  } 

added an id to the search button:

<span id="top-bar-search-icon" @click="showPopup = !sho    wPopup">&#128269;</span>

and modified my method:

  methods: {
    clickOutsidePopup: function(event) {
      if (event.target.id !== "top-bar-search-icon")
        this.showPopup = false;
    }
  },
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175