2

I'm trying to dynamically render some HTML in a Vue.js component. I'm successfully rendering the HTML. However, I don't know how to wire-up the events for the dynamically rendered elements. I've created a small example. This example probably looks like I've over complicated things. However, it's just a small part of the real example. The example can be seen in this JSFiddle, and the code looks like this:

new Vue({
  el: '#app',
  data: {
    items: [
      { 
        name:'Item 1', 
        isHtml:true, 
        mold: function() {
          return '<button @click="onButtonOneClick">click</button>';
        }
      },

      {
        name: 'Item 2',
        isHtml: false
      },

      {
        name:'Item 3',
        isHtml: true,
        mold: function() {
          return '<button @click="onButtonThreeClick">click</button>';
        }
      }
    ]
  },

  methods: {
    getHtml: function(i) {
      return i.mold();
    },

    onButtonOneClick: function() {
      alert('First Item Clicked');
    },

    onButtonThreeClick: function() {
      alert('Third Item Clicked')
    }
  }
})

If you run this fiddle, you'll notice that my two buttons look fine on the screen. However, the related click events don't get fired when you actually click the buttons. From what I can see, it looks like the HTML doesn't get fully compiled. I may be wrong. But, it's what it looks like based on what i see in the Chrome Dev Tools.

How do I wire up events for dynamically generated HTML in a Vue.js component?

1
  • I generally agree that this isn't a great approach, but statements like "This is never going to work" are a little strong. Here is an example of the kind of thing you need to do to get this to work. jsfiddle.net/ozf8kq1z/3 Commented Nov 22, 2017 at 15:10

3 Answers 3

1

You're trying to render 'functional html' which is basically the essence of what Vue does for you. Just render your list as you do, and add in your data in an attribute like 'is_button', and output the html for the button in the v-for and add its events. e.g.

   <div v-for="(item, index) in items">
    <button v-if="item.is_button" @click="onButtonClick(index)">
    <div>item.content</div>
   </div>

Good luck

Sign up to request clarification or add additional context in comments.

Comments

0

Your example goes against everything that Vue is trying to accomplish. I suggest reading up on Vue in their docs or following some tutorials. I am not saying it can't be done because you could certainly bind events later but it is not wise.

Certainly something like this is not going to work:

mold: function() {
  return '<button @click="onButtonThreeClick">click</button>';
}

That is because Vue has already rendered the markup when you inject this.

It is difficult to tell what you are trying to achieve exactly but perhaps something like this can help you out:

https://jsfiddle.net/ozf8kq1z/2/

(Open your console)

Comments

0

I'm sorry to be a nuisance, but why have you got vue markup in your data :? This is never going to work. Can you explain what led you down this path? Why can't your markup stay in a template :?

Vue does have a v-html directive for popping little bits of markup out of javascript into templates, but Vue tags in this markup are not processed, and it's one of those features you should use with a bad conscience.

Event listeners outside of Vue, attached after Vue has rendered, do function, but then you've really got to look at yourself in the mirror and ask "oh what have I done"?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.