JemoeE
JemoeE

Reputation: 600

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>

Upvotes: 7

Views: 14049

Answers (3)

The_ehT
The_ehT

Reputation: 1230

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>

Upvotes: 0

asemahle
asemahle

Reputation: 20805

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>

Upvotes: 5

leocoder
leocoder

Reputation: 196

You should try to create a component and pass as prop the user var. Here is an example of what you can do.

<users-list v-for="user in users" v-bind:user="user"></users-list>

Here is a quick functional example: https://jsfiddle.net/leocoder/tor13m26/1/

Use v-html for that purpose it seem to be a bad practice.

Upvotes: 0

Related Questions