[Vuejs]-Programmatically add v-on directives to DOM elements

1👍

You could try something like this:

<template>
    <span v-for="tag in tags" @click="showModal(tag)" v-text="tag"></span>
</template>

<script>
    export default {
        data() {
            return {
                tags: ['Tag 1', 'Tag 2', 'Tag 3']
            }
        },
        methods: {
            showModal(tag) {
                console.log("Showing modal for tag:", tag)
            }
        }
    }
</script>

Hope this helps!

👤mtflud

1👍

You can add a method which is called on clicks that reads the element’s HTML content.

The template:

<span @click="doStuff">Tag 1</span>
<span @click="doStuff">Tag 2</span>
<span @click="doStuff">Tag 3</span>

The method:

doStuff(e) {
  this.showModal = e.target.innerHTML
}

0👍

You could set up a method to call when the tag is clicked and pass the id of the tag that was clicked through to handle appropriately.

Assuming that you have an array of the tag text:

data: function() {
  return {
    tagTotal: ['Tag 1', 'Tag 2', 'Tag 3'];
  }
}

Then in the HTML section:

<span v-for="tag in tagTotal" @click="methodToCall(tag)">
  {{ tag }}
</span>

Then in your mounted, methods, or created section you could add:

mounted: {
  methodToCall: function(tag) {
    showModal = tag;
    // or 'this.showModal = tag' if showModal is a part of the componenet.
  }
}

0👍

If direct-process Dom elements, custom directive will be one option.

Vue.config.productionTip = false

let vMyDirective = {}
vMyDirective.install = function install (_Vue) {
  _Vue.directive('my-directive', {
    inserted: function (el, binding, vnode) {
      el.addEventListener('click', () => {
        _Vue.set(vnode.context, binding.value.model, el.innerHTML)
      }, false)
    }
  })
}

Vue.use(vMyDirective)

new Vue({
  el: '#app',
  data() {
    return {
      testValues: ['label a', 'label b'],
      showModal: 'nothing!!!'
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <h2>showModal: {{showModal}}</h2>
  <div>
    <p v-for="(item, index) in testValues" v-my-directive="{'model': 'showModal'}">Test:<span>{{item}}</span></p>
  </div>
</div>
👤Sphinx

0👍

I’ve finally added the listeners manually with vanilla js, in order to save code:

mounted: function() {
    let spans = document.querySelectorAll('span');

    spans.forEach(el => {
      el.addEventListener('click', this.clickTag);
    })
}
methods: {
    clickTag(event) { this.showModal = event.target.innerHTML }
}

It’s important not using an arrow function for mounted because otherwise it won’t bind the vue instance for this.

Thanks for your answers.

Leave a comment