0

In order to separate my code and make it cleaner, I would like to use a Vue component as an HTML template, pass some parameters to the template and get the resulting HTML back as a string.

I have made a simple example that almost works, but for some reason the returned HTML is not up to date. When I hit "click me" I do get an HTML-string from the "MyDetails"-component, but it shows the value passed from the previous time, I hit the "click me"-button, instead of showing the actual value.

Main.vue

<template>
  <div>
    <p>
      <myDetails ref="myDetails"/>
    </p>
    <button @click="handleClick">click me</button>
    <p>{{message}}</p>
  </div>
</template>

<script>
import MyDetails from "/components/MyDetails.vue";

export default {
  name: "hello",
  components: {
    MyDetails
  },
  methods: {
    handleClick() {
      this.$refs.myDetails.setMessage(new Date().getTime());
      this.message = this.$refs.myDetails.$el.outerHTML;
    }
  },
  data() {
    return {
      message: ""
    };
  }
};
</script>

MyDetails.vue

<template>
  <div style="background-color:red">
    <h1>MyDetails component</h1>
    <p>{{message}}</p>
  </div>
</template>
<script>
export default {
  name: "hello",
  data() {
    return {
      message: ""
    };
  },
  methods: {
    setMessage(value) {
      this.message = value;
    }
  }
};
</script>

In the example above "MyDetails" is part of the template from the beginning. Is it possible to load it dynamically in the click-handler instead, so it doesn't show up, before I hit the "click me"-button?

Please see code here: https://codesandbox.io/s/vue-fullcalendar-example-50sv9?fontsize=14&hidenavigation=1&theme=dark

1 Answer 1

1

Updating the DOM takes time, you are immediately getting the myDetails outerHTML after you are changing its data, which doesn't give time for the change to propagate. Setting a slight delay as follows will give output as expected:

handleClick() {
    this.$refs.myDetails.setMessage(new Date().getTime());
    setTimeout(() => {
        this.message = this.$refs.myDetails.$el.outerHTML;
    }, 100) 
}

For demo, see the sandbox here

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

4 Comments

thanks. It works. Do you know whether I can load the component dynamically and then pass the parameters or if I need to include the component in the markup from the beginning?
I am not really sure what you mean. To pass parameters to a component, you can use props. To reuse a component in another component, import and register the child component in the parent component. Or use Dynamic component with vue?
I would like to display a calendar with concerts and use a component as the HTML-template for each concert. Please see the "eventRender"-callback: [codesandbox.io/s/… As you can see the template component is visible below the calendar and it seems it is only the data from the last concert, that is shown. So instead of embedding the component from the beginning, would it be possible to load it dynamically per concert, pass the data for the concert, get the HTML and discard the component again?
I figured it out by using Vue.extend(). I first import EventDetails from "/components/EventDetails.vue" and then create a class which can be instantiated: var EventDetailsClass = Vue.extend(EventDetails); I then create an instance of the class: let EventDetailsInstance = new EventDetailsClass(); I then pass the data, mount the component and get the HTML. Sandbox here: [codesandbox.io/s/vue-fullcalendar-example-pqctv]

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.