Dropdown Menu (VUEJS/Javascript)

Asked

Viewed 479 times

3

I’m trying to make a dropdown menu in Vue (I don’t want to use Bootstrap-Vue), so I created a isActiveDrop and defined how true, and every time I click the button to open it is set to false, so the menu appears and disappears, but how would you make that menu disappear when clicking outside? without having to click on the icon, just clicking outside it?

<i class="fa fa-menu" @click="menu"></i>

<ul  :class="{hidden: isActiveDrop}">
  <li>TESTE</li>
</ul>

1 answer

3


Hello,

Looking for a simple way to implement functionality click-Outside in the element, I found this directive. Besides, I couldn’t think of any other way than by directive.

Below is an adaptation of directive for ES5 and a few more modifications.

Vue.directive('click-out', {
  bind: function(element, binding, node) {
    // verifica se o parametro da diretiva é diferente de um objeto do tipo function.
    if(typeof binding.value !== 'function') {
      var component = node.context.name;
      var text = '[Vue-click-out:] a expressão informada deve ser uma função';
      if(component) {
        text += ' Component: ' + component;
      };
      console.warn(text);
    };
    // cria o evento e atribui ao elemento
    var bubble = binding.modifiers.bubble;
    var handler = function(evt) {
      if(bubble || (!element.contains(evt.target) && element !== evt.target)) {
        binding.value(evt);
      };
    };
    element.__vueClickOutside__ = handler;
    // adiciona o evento que trata os cliques fora do component
    document.addEventListener('click', handler);
  },

  unbind: function(element) {
    // remove o evento que trata cliques fora do componente
    document.removeEventListener('click', element.__vueClickOutside__);
    element.__vueClickOutside__ = null;
  }
});

Implementation

Registering the above directive in your code, an example of usage will look like this:

Vue.directive('click-out', {
  bind: function(element, binding, node) {
    // verifica se o parametro da diretiva é diferente de um objeto do tipo function.
    if (typeof binding.value !== 'function') {
      var component = node.context.name;
      var text = '[Vue-click-out:] a expressão informada deve ser uma função';
      if (component) {
        text += ' Component: ' + component;
      };
      console.warn(text);
    };
    // cria o evento e atribui ao elemento
    var bubble = binding.modifiers.bubble;
    var handler = function(evt) {
      if (bubble || (!element.contains(evt.target) && element !== evt.target)) {
        binding.value(evt);
      };
    };
    element.__vueClickOutside__ = handler;
    // adiciona o evento que trata os cliques fora do component
    document.addEventListener('click', handler);
  },

  unbind: function(element) {
    // remove o evento que trata cliques fora do componente
    document.removeEventListener('click', element.__vueClickOutside__);
    element.__vueClickOutside__ = null;
  }
});

var navList = new Vue({
  el: '#app',
  data: function() {
    return {
      visible: false
    }
  },
  methods: {
    show: function() {
      this.visible = !this.visible;
    },
    hide: function() {
      this.visible = false;
    }
  }
})
.dropdown {
  display: none;
}

.dropdown.active {
  display: block;
}
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <ul>
    <li>Home</li>
    <li @click="show" v-click-out="hide">
      Products
      <ul class="dropdown" :class="{active: visible}">
        <li>Product 1</li>
        <li>Product 2</li>
      </ul>
    </li>
    <li>About us</li>
  </ul>
</div>

Basically you have the v-bind or : for class checking whether visible is true (true) and assigning the class .active where appropriate. The v-on or @ for the event click, assigning by the method show, true or false (the opposite of the current value in the property) visible and the directive v-click-out, assigning by the method hide, false to visible.

Testing

...<li @click="show" v-click-out="visible = true">...

inserir a descrição da imagem aqui

In the case of this directive it is possible to only inform a method for execution, but you can adjust it to receive an expression from Vuejs.

Information

More about custom directives (directives) in Vuejs 2.x here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.