2

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?

user1081577
  • 469
  • 2
  • 8
  • 25

1 Answers1

2

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/

craig_h
  • 31,871
  • 6
  • 59
  • 68
  • Do you have a link to any documentation of `:is`? – Ed_ May 29 '17 at 15:37
  • 1
    Absolutely, you can find it under the [Dynamic Components](https://vuejs.org/v2/guide/components.html#Dynamic-Components) section of the official Vue.js docs. – craig_h May 29 '17 at 15:58
  • This would be fine in case the fragments of DOM were small and fixed, not a dynamic count of them. Using $mount or a directive I could process arbitrary DOM fragments, using components I have to specify their names, which probably has to be autogenerated component1, component2, which would be very ugly and unreliable. – Dmitriy Sintsov Apr 03 '18 at 09:48