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>
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.
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.
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.
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.
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.
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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With