Tom
Tom

Reputation: 41

vuejs - how to convert ajax loaded html into vuejs components

I have an #app container with some html, and I create Vue instance on the #app, all the content is compiled and converted to Vuejs components. Then I ajax in another html string, and I need to somehow compile that into components, how do I do that?

Upvotes: 4

Views: 1802

Answers (2)

Julian Paolo Dayag
Julian Paolo Dayag

Reputation: 3739

Such thing is not considered a good practice in Vue, but you can actually create components dynamically by using the Vue with template compiler.

Usually, the stand-alone distribution of Vue where you just include a script tag into your page already includes a template compiler.

Upvotes: 0

ghybs
ghybs

Reputation: 53350

That is the use case for the template option, which can either reference to a <template> with specific ID in your DOM (like you do with your app using the el option), or directly your HTML template:

Vue.component({
  template: `<span class="myItem"><slot></slot></span>`
});

You can easily turn it into an Async Component by providing a function to your component list, which returns a Promise that resolves with the component constructor (e.g. using Vue.extend):

const MyLoadingComponent = Vue.extend({
  template: '#my-loading',
});

new Vue({
  el: '#app',
  data() {
    return {
      items: [],
    };
  },
  components: {
    'my-component': loadComponentWithLoading,
  },
  methods: {
    addItem() {
      this.items.push(Math.random());
    },
  },
});

// https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Handling-Loading-State
function loadComponentWithLoading() {
  return {
    component: loadComponent(),
    loading: MyLoadingComponent,
  };
}

// https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Async-Components
function loadComponent() {
  return new Promise(function(resolve, reject) {
    loadComponentHtml().then((html) => {
      resolve(Vue.extend({
        // https://v2.vuejs.org/v2/api/#template
        template: html,
      }));
    });
  });
}

function loadComponentHtml() {
  return new Promise(function(resolve, reject) {
    setTimeout(() => {
      resolve(`<span class="myItem"><slot></slot></span>`);
    }, 2000);
  });
}
.myItem {
  color: green;
}

.myLoading {
  font-style: italic;
  color: red;
}
<script src="https://unpkg.com/vue@2"></script>

<div id="app">
  <button @click.prevent="addItem">Add some list items</button>
  <ul>
    <li v-for="item of items">
      <my-component>{{item}}</my-component>
    </li>
  </ul>
</div>

<template id="my-loading">
  <span class="myLoading">Loading…</span>
</template>

Upvotes: 1

Related Questions