Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS Custom directive + emit event

I need to $emit an event from a custom directive. Is it possible?

directive.js:

vnode.context.$emit("myEvent") // nothing append
vnode.child.$emit("myEvent")   // error
vnode.parent.$emit("myEvent")  // error

component.vue:

<div v-directive.modifier="binding" @myEvent="method()"></div>

Do you know if it's possible or if there is any trick?

Thanks

like image 815
Brice Chaponneau Avatar asked Mar 13 '18 19:03

Brice Chaponneau


People also ask

How do you emit events in Vue?

Emitting Events with setup()$emit() to send our event. Instead, we can access our emit method by using the second argument of our setup function – context . context has access to your components slots, attributes, and most importantly for us, its emit method. We can call context.

Do Vue events bubble?

Vue events don't bubble the component tree on their own. However when writing wrapper components this can be the desired behaviour. This code registers a global bubble directive which allows to re-emit all given events: Let's say we want to bubble events start , accelerate and brake of our component Car .

How do you emit in NUXT?

What is emit in Nuxt? In NUXT any component in a page can emit an event and any other component can listen to it. To emit an event from any component use, $nuxt. $ emit ('my-custom-event') this.


1 Answers

A <div> is not a VueComponent, which means it doesn't have an $emit method.

So to make your Vue custom directive emit an event, you will have to do some checking first:

  • If the directive was used in a Vue custom component, then call $emit() of that component's instance
  • If the directive was used in a regular DOM element (...because there's no $emit()...), then dispatch a native DOM event using .dispatchEvent.

Luckily, Vue's v-on listeners respond to native custom events.

That should be all. Demo implementation below.

Vue.component('my-comp', {
  template: `<input value="click me and check the console" size="40">`
});

Vue.directive('my-directive', {
  bind: function (el, binding, vnode) {

    // say you want to execute your logic when the element is clicked
    el.addEventListener('click', function (e) {
    
      var eventName = 'my-event';
      var eventData = {myData: 'stuff - ' + binding.expression}
      if (vnode.componentInstance) {
      	vnode.componentInstance.$emit(eventName, {detail: eventData}); // use {detail:} to be uniform
      } else {
      	vnode.elm.dispatchEvent(new CustomEvent(eventName, {detail: eventData}));
      }

    })
  }
})

new Vue({
  el: '#app',
  methods: {
    handleStuff(e) { console.log('my-event received', e.detail); }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <div v-my-directive.modifier="'native element'" @my-event="handleStuff">CLICK ME AND CHECK THE CONSOLE</div>
  <hr>
  <my-comp v-my-directive.modifier="'custom component'" @my-event="handleStuff"></my-comp>
</div>
like image 54
acdcjunior Avatar answered Sep 19 '22 11:09

acdcjunior