Reputation: 4050
I'm new to Vue.js, I've used AngularJS for some time and in angular we used to load templates such as,
template: '/sometemplate.html',
controller: 'someCtrl'
How can we do such a thing in Vue, instead of keeping large HTML templates inside JavaScript like this,
new Vue({
el: '#replace',
template: '<p>replaced</p>'
})
This is OK for small templates but for large templates is this practical?
Is there a way to load external template HTML or use HTML template inside a script tag like in Vue?
<script type="x-template" id="template">HTML template goes here</html>
Upvotes: 81
Views: 127878
Reputation: 28448
You can try this:
for Vue2 : https://github.com/FranckFreiburger/http-vue-loader
for Vue3 : https://github.com/FranckFreiburger/vue3-sfc-loader
Example (Vue2) :
new Vue({
components: {
'my-component': httpVueLoader('my-component.vue')
},
...
Example (Vue3) :
Vue.createApp({
components: {
'my-component': Vue.defineAsyncComponent(() => loadModule('./myComponent.vue', opts))
},
...
Upvotes: 21
Reputation: 2360
there are at least 2 ways to achieve what you want, on of them (x-templates) already mentioned by Bill Criswell, but I think it worth to add an example
Define your component like this
Vue.component('my-checkbox', {
// id of x-template
template: '#my-template'
});
Add html file with your x-template (id should match the one you specified in the component)
<script type="text/x-template" id="my-template">...</script>
Another approach (and I like this one better) would be to use inline template
Define your template like this
Vue.component('my-template', {});
Add html file with your component and template inside it
<my-template inline-template>place for your html</my-template>
Just don't forget to add inline-template
attribute, otherwise it won't work
Upvotes: 1
Reputation: 32921
You can use the script tag template by just referring to its id
.
{
template: '#some-id'
}
Though, I highly recommend using vueify (if you use browserify) or vue-loader (if you use webpack) so you can have your components stored in nice little .vue
files like this.
Also, the author of Vue wrote a nice post about the topic of external template urls:
https://vuejs.org/2015/10/28/why-no-template-url/
Upvotes: 34
Reputation: 121
I've tried http-vue-loader and it works fine. This library is easy to use and has good documentation and examples
Although you can't load templates from filed directly you still can keep html in separate single-file components. You can even skip <script>...</script>
part.
my-component.vue
<template>
<div class="hello">Hello {{who}}</div>
</template>
index.html
<!doctype html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/http-vue-loader"></script>
</head>
<body>
<div id="my-app">
<my-component></my-component>
</div>
<script type="text/javascript">
new Vue({
el: '#my-app',
components: {
'my-component': httpVueLoader('my-component.vue')
}
});
</script>
</body>
</html>
Both files should be placed in one folder at the same level
Upvotes: 9
Reputation: 772
// template.vue
<template>
<div class="helloworld">
<h1>Hello world</h1>
</div>
</template>
<script>
import src from './src'
export default src
</script>
and in a separate file
// src.js
export default {
name: 'helloworld',
props: {},
...
}
Then in your component registration
import helloworld from './helloworld/template.vue'
new Vue({
components: {
'helloworld': helloworld
},
...})
This way you get the best of both worlds and you don't have to force yourself to build templates within a string.
new Vue({
components: {
'helloworld': () => import(/* webpackChunkName: "helloworld" */ './helloworld/template.vue')
},
...})
This will load helloworld.js (which will contain all that component's code) on request of that page in the browser.
Of course, all the above assumes you are using ES6 with import
capabilities
Upvotes: 4
Reputation: 2609
Use browserify to bundle everything like this:
//Home.js
import Vue from 'vue';
var Home = Vue.extend({
template: require('./Home.vue')
});
export default Home;
//Home.vue
<h1>Hello</h1>
// And for your browserify bundle use a transform called stringify
... .transform(stringify(['.html', '.svg', '.vue', '.template', '.tmpl']));
Upvotes: 0
Reputation: 1108
David, that is a nice example, but what's the best way to make sure the DOM is compiled?
https://jsfiddle.net/q7xcbuxd/35/
When I simulate an async operation, like in the example above, it works. But as soon as I load an external page "on the fly", Vue complains because the DOM is not ready.
More specifically:
Uncaught TypeError: Cannot set property 'vue' of undefined
Is there a better way to do this than to call $compile
when the page has loaded? I've tried with $mount
, but that didn't help.
UPDATE: Never mind, I finally figured out how to do it:
Vue.component('async-component', function (resolve, reject) {
vue.$http.get('async-component.html', function(data, status, request){
var parser = new DOMParser();
var doc = parser.parseFromString(data, "text/html");
resolve({
template: doc
});
});
});
And in the actual template, I removed the
<script id="someTemplate" type="text/x-template"></script>
tags and only included the html.
(This solution requires the http loader from https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.10/vue-resource.min.js)
Upvotes: 16
Reputation: 17246
You can use this approach with superagent:
var promise = superagent.get("something.html")
.end(function (error, response) {
if (error) {
console.error("load of something.html failed", error));
return;
}
var parser = new DOMParser()
var doc = parser.parseFromString(response.text, "text/html");
document.body.appendChild(doc.scripts[0]);
});
Just put your <script>
tag based template inside of something.html
on your server.
If you are using jQuery, .load should work.
Just make sure this completes before the DOM in question is compiled by Vue. Or use $mount to manually set things up.
Upvotes: 0