10

This is my code:

<template>
    <div>      
      <div v-html="data"></div> <button v-on:click="replace">Click Me to replace div contents</button>
    </div>
</template>
<script>
export default {
  data() {
    return {
      data: "I will be replaced once you click on button"
    }
  },
  methods: {
    clickMe() {
      alert("worked");
    },
    replace(){
      this.data = "Why does click me not work? It is loaded from server via ajax <a href v-on:click.prevent='clickMe'>Click Me</a>";
    }
  }
};
</script>

Here if I click on Click Me to replace div contents the content is replaced but the event handler clickMe does not fire. This data would come from server and I need to compile this string and use it from within the Vue's context so Vue can handle events etc.

How can I have the dynamic string downloaded from server work? I am using Vue 2.

2
  • What do you intend to see when you click on the button? Commented Nov 9, 2017 at 13:31
  • @samayo: Thanks for replying. When "Click Me to replace div contents" is clicked I would see Why does click me not work? It is loaded from server via ajax <a href v-on:click.prevent='clickMe'>Click Me</a> This is correct however now when I click on Click Me I do not see alert. That is my problem. Commented Nov 9, 2017 at 13:34

4 Answers 4

15

Since v-html isn't compiled you will have to create a mini component like this to get around the issue:

new Vue({
  el: '#app',
  data () {
    return {
      data: ``
    }
  },
  
  computed: {
    compiledData () {
      return {
      	template: `<p>${this.data}</p>`
      }
    }
  },
  
  methods: {
    replace () {
       this.data = `Now click on me <a href='#' @click.prevent='alert("yo")'> here </a>`
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>


<div id="app">
  <component :is="compiledData" ></component>
  <button v-on:click="replace">Click Me to replace div contents</button>
</div>

The above code compiles the string content and thus you can run/execute the function as intended

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

2 Comments

That's a neat solution.
amazing samayo. You are brilliant!
5

Other solution using Vue components (codepen):

<script src="https://unpkg.com/vue"></script>
<div id="app">      
  <div id="someId"></div> <button v-on:click="replace">Click Me to replace div contents</button>
  <component :is="currentView"></component>
</div>

<script>
let app = new Vue({
  el: '#app',
  data: {
    currentView: null   
  },
  methods:{
    replace: function(){
      var templateFromServer = getTemplate();
       var comp=Vue.component('template-from-server', {
          template: templateFromServer,
          methods:{
            clickMe:function (){
              console.log("click");
            }            
          }
        });   
      this.currentView = comp;
    }   
  }
});

function getTemplate(){
  return "<a href v-on:click.prevent='clickMe'>Click Me</a>"
}
</script>

Comments

0

v-html is not compiled as a Vue template. From the docs:

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.

see: https://v2.vuejs.org/v2/api/#v-html

4 Comments

Thank you. Do you then know what would be a potential way to solve this issue?
You have to pass it a template
@samayo: I am unable to follow. Could you share the code please?
@TimLiberty Ok, check my answer
-1

You can not render VueJS code from a html string.

You can solve this issue by using v-if

<div>
<div v-if="data">I will be replaced once you click on button</div> 
<div v-else>Why does click me not work? It is loaded from server via ajax <a href @click.prevent='clickMe'>Click Me</a></div>
<button @click="replace">Click Me to replace div contents</button>
</div>

<script>
export default {
  data() {
    return {
      data: true
    }
  },
  methods: {
    clickMe() {
      alert("worked");
    },
    replace(){
      this.data = !this.data;
    }
  }
};

You can call normal javascript function from string but not vuejs function so onclick event would also work.

2 Comments

The full string is returned from the server along with @click so this solution will not work.
As mention is vuejs.org/v2/api/#v-html "The contents are inserted as plain HTML - they will not be compiled as Vue templates". You need to use components and pass the server returned string as a template.

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.