Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically bind custom events for dynamic components in VueJS

Tags:

vue.js

vuejs2

In my vuejs app I use dynamic component in the following way:

<mycomponent>
  <component ref="compRef" :is="myComponent" v-bind="myComponentProps"></component>
  <div class="my-buttons">        
    <my-button label="Reset" @click="reset()"/>
  </div>
</mycomponent >

myComponent is a prop on the parent component which hold the actual component to inject. myComponentProps are also prop which holds the porps for the injected instance.

I would like to know how can I also dynamically bind listeners to the component - I have understand that I cannot send an object to v-on with multiple events.

I was thinking about adding it programatically however haven't found any info about how it can be done for Vue custom events (kind for addEventListener equivalent for custom events)

Any tip would be much appreciated!

like image 792
Myupe Avatar asked Jan 14 '18 14:01

Myupe


1 Answers

With Vue 2.2+, you can programmatically add an event listener with $on(eventName, callback):

new Vue({
  el: '#app',
  created() {
    const EVENTS = [
      {name: 'my-event1', callback: () => console.log('event1')},
      {name: 'my-event2', callback: () => console.log('event2')},
      {name: 'my-event3', callback: () => console.log('event3')}
    ]

    for (let e of EVENTS) {
      this.$on(e.name, e.callback); // Add event listeners
    }

    // You can also bind multiple events to one callback
    this.$on(['click', 'keyup'], e => { console.log('event', e) })
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <div>
    <!-- v-on:EVENTNAME adds a listener for the event -->
    <button v-on:click="$emit('my-event1')">Raise event1</button>
    <button v-on:click="$emit('my-event2')">Raise event2</button>
    <button v-on:click="$emit('my-event3')">Raise event3</button>
  </div>
  <div>
    <!-- v-on shorthand: @EVENTNAME -->
    <button @click="$emit('my-event1')">Raise event1</button>
    <button @click="$emit('my-event2')">Raise event2</button>
    <button @click="$emit('my-event3')">Raise event3</button>
  </div>
</div>

With Vue 2.6+, you can add an event listener dynamically in the template:

new Vue({
  el: '#app',
  data: {
    eventname: 'click',
  },
  methods: {
    handler(e) {
      console.log('click', e.target.innerText)
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <button @[eventname]="handler">Raise dynamic event</button>

  <!-- Set dynamic key to null to remove event listener -->
  <button @click="eventname = null">Unbind event</button>
</div>

You can also declaratively bind multiple event listeners with v-on="{event1: callback, event2: callback, ...}":

new Vue({
  el: '#app',
  methods: {
    onClick() { console.log('click') },
    onKeyUp(e) { console.log('keyup', e.keyCode) }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <input type="text" placeholder="type here" v-on="{click: onClick, keyup: onKeyUp}">
</div>
like image 195
tony19 Avatar answered Oct 15 '22 10:10

tony19