'Vue 2 - render components from an ajax response
Is there a way to render components that come from an ajax response? For example, I registered a component "Test" and in the ajax response I have:
<p>dummy paragraph</p>
<test></test> <!-- vue component I want to render -->
<p>another dummy paragraph</p>
My final goal is to make a shortcode that lets the user insert a router link in the content area.
I'm using Vue 2, vue router
Edit: here is a demo https://jsfiddle.net/Paulius_Krutkis/4mb1ypqs/
Solution 1:[1]
I am not sure, what is the exact issue you are facing here, If you are looking for how to render the HTML returned from ajax call, You can use v-html which can render the string variable having HTML.
However be aware:
Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.
So v-html
will not compile and and render any vue component as you may expect, you may have to find some other solution for it.
Alternet way
However as you are saying, you need a way to render components that come from an ajax response, You can take help of Async-Components, where you define your component as a factory function that asynchronously resolves your component definition.
see the demo here: https://jsfiddle.net/4mb1ypqs/1/
Solution 2:[2]
Yes, there is way for doing this. Follow these steps:
- Register the component (which will be sent as an ajax response) globally.
import Vue from 'vue'
import Test from './some/folder/Test.vue'
Vue.component('test', Test)
- Either add Vue to the window object or export it and import it wherever you need it. Here i will add it to the global window object so that i can easily access it within the browser console.
window.Vue = Vue
- When you get the ajax response with the uncompiled DOM element (
<test></test>
) you can decide if you want to insert it directly to your DOM and compile it afterwards or compile it first and then mount it to the DOM. Lets say you inserted the component template directly to the DOM like in your example. Notice the wrapper element.
<p>dummy paragraph</p>
<div id="testapp">
<test></test>
</div>
<p>another dummy paragraph</p>
- Create a new Vue instance and tell it where it should mount. Since your test component is already registered globally, vue knows how it looks like and will compile it once it sees it in the DOM. Alternatively, you can also add it here within your "components" property.
new window.Vue({
el: '#testapp',
})
- Done!
Info: VueDevtools will not recognize your new compiled component If you have already a root vue instance mounted initially. To make it work you must tell the newly created instance that it belongs to a parent instance:
var vm = new Vue({
el: '#app',
});
new window.Vue({
el: '#testapp',
parent: vm,
});
Notice: The new vue instance will NOT share data with other instances. This approach is only "meaningful" (of course this whole procedure is not recommended) when you have independent components like for example a text-input component, that is only there to send data to the server independently.
Hope it helps someone out there!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |