user1081577
user1081577

Reputation: 469

Vue.js 2.0 this.$compile

How do can you compile a HTML string to template within a component method? This was possible in Vue 1 like in this jsfiddle

new Vue({
    el: '#app',
    data: {
        sampleElement: '<button v-on="click: test()">Test</button>'

    },
    methods:{
        addNewElement: function(){

           var element = $('#app').append(this.sampleElement);
            /* compile the new content so that vue can read it */
           this.$compile(element.get(0));
        },
        test: function(){
           alert('Test');
        }
    }
});

How can you do this in Vue 2?

Upvotes: 2

Views: 4519

Answers (1)

craig_h
craig_h

Reputation: 32714

This is no longer possible, however, Vue 2 is data driven, so you shouldn't be trying to affect the DOM manually at all, instead you should bind elements to the underlying data in your view model. With that in mind your example will need to be re-written. Firstly, start by making your element a component:

Vue.component('my-button', {
  template: '<button v-on:click="test()">{{text}}</button>',
  props: ['text'],
  methods: {
    test() {
      alert('Test');
    }
  }
});

Then you can create your main view model and add your button component using a v-for:

Markup:

  <button v-on:click="addNewElement()">Add Element</button>
  <my-button v-for="button in buttons" :text="button"></my-button>

View model:

new Vue({
  el: '#app',
  methods: {
    addNewElement: function() {
       this.buttons.push('Test');
    }
  },
  data: {
    buttons: []
  }
});

In this example we are pushing buttons to an array that will then be displayed on the page, rather than manually appending them to the template.

Here's the JSFiddle: http://jsfiddle.net/10q9je5a/

If you want something more generic, then you can simply create an array of different components and use :is to let Vue know which component to render:

Markup:

<div id="app">
  <button v-on:click="addNewElement()">Add Element</button>
  <div :is="element.component" v-for="element in elements" v-bind="element.props"></div>
</div>

View Model:

new Vue({
  el: '#app',
  methods: {
    addNewElement: function() {
       this.elements.push({component: 'my-button', props: {text: 'Test'}});
    }
  },
  data: {
    elements: []
  }
});

Here's the JSFiddle for that: http://jsfiddle.net/cxo5eto0/

Upvotes: 2

Related Questions