Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set "v-on" on content added with "v-html" in Vue

Is it possible in Vue to add v-on events on strings added in v-html? In the example, when clicking the 'Maggie' link nothing happens. It doesn't seem to be registered with Vue.

Or maybe there's another way to do it? I'm using Vue.js 2.1.3

Javascript

window.onload = function() {
    new Vue({
        el: '#app',
        data: {
            users: ['Homer', 'Marge', 'Bart', 'Lisa', '<a href="#" v-on:click="click_user">Maggie</a>']
        },
        methods: {
            click_user: function() {
                console.log('Click user')
            },
        }
    })
}

HTML

<div id="app">
    <div v-for="user in users" v-html="user"></div><br>
    <a href="#" v-on:click="click_user">This works.</a>
</div>
like image 517
JemoeE Avatar asked Dec 07 '16 14:12

JemoeE


People also ask

How to use V-on click event in Vue JS?

The v-on:click directive is a Vue.js directive used to add a click event listener to an element. First, we will create a div element with id as app and let’s apply the v-on:click directive to a element. Further, we can execute a function when click even occurs.

What is V-HTML in Vue JS?

Vue.js | v-html directive. The v-html directive is a Vue.js directive used to update a element’s innerHTML with our data. This is what separates it from v-text which means while v-text accepts string and treats it as a string it will accept string and render it into HTML.

How do I use V-on in Vue?

You can use v-on: to listen to any native event, like: Vue has a convenient shorthand for v-on : the @ symbol. For example, @click is functionally equivalent to v-on:click. Using @ saves you a few keystrokes, but v-on is more readable for people who aren't familiar with Vue.

How do I emit an update event in Vue?

In Vue methods and expressions, you have access to a $emit () function that lets you emit an event up the component tree to the parent component. In the below example, the input-name component emits a 'update' event. The top-level app listens for 'update' events using v-on:update, and changes the name accordingly.


2 Answers

From the vue docs:

Updates the element’s innerHTML. Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates. If you find yourself trying to compose templates using v-html, try to rethink the solution by using components instead.

This means that v-on will not work within v-html , because it requires vue to work.


Potential Solution to Your Specific Problem

Conditionally render a link using v-if, otherwise render plain text.

new Vue({
  el: '#app',
  data: {
    users: [
      { name: 'Homer', clickable: false },
      { name: 'Marge', clickable: false },
      { name: 'Bart', clickable: false },
      { name: 'Lisa', clickable: false },
      { name: 'Maggie', clickable: true },
    ]
  },
  methods: {
    click_user: function() {
      console.log('Click user')
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.0/vue.js"></script>

<div id="app">
  <div v-for="user in users">
    <div v-if="!user.clickable">{{user.name}}</div>
    <a v-if="user.clickable" href="#" v-on:click="click_user">{{user.name}}</a>
  </div>
</div>
like image 180
asemahle Avatar answered Sep 28 '22 16:09

asemahle


Rendering <a href="#" v-on:click="click_user">Maggie</a> with v-html will not bind any click event. You can read more about it in doc. It will just render v-on:click as attribute.

Keep simple array of data. I don't think you need v-html. Use either text or index with if(one or two) or switch(for multiple) condition for triggering event.

window.onload = function() {
    new Vue({
        el: '#app',
        data: {
            users: ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']
        },
        methods: {
            click_user: function(text) {
              if(text=='Maggie') console.log('Click user')
            }
        }
    })
}

<div id="app">
   <div v-for="user in users" v-on:click="click_user(user)">{{user.name}}</div><br>    
</div>

Or

window.onload = function() {
  new Vue({
      el: '#app',
      data: {
          users: ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']
      },
      methods: {
        click_user: function(index) {
          if(index==4) console.log('Click user')
        }
      }
   })
}

<div id="app">
   <div v-for="user,index in users" v-on:click="click_user(index)">{{user.name}}</div><br>    
 </div>
like image 30
The_ehT Avatar answered Sep 28 '22 18:09

The_ehT