Closed dimitri-koenig closed 7 years ago
Although I don't quite understand the use case, you can do something like this:
components: {
child: {
template: document.querySelector('#child-template') ? '#child-template' : '<div>...</div>'
}
}
Hm, does not quite solve my issue :-/
My use case is this: I want to compile a whole application with templates within one single component file (with style, script and template sections) and deliver it within a package. But for easier customization where only template modifications are needed, you shouldn't have to go directly into the components but rather create a "x-template" within your html file which overrides the already provided template in the one-component-file.
Any idea on how I could solve that?
Are you using single file components?
The application is using single file components, yes.
In that case this is not possible because single-file components' templates are pre-compiled at build time. Also allowing users to arbitrarily overwrite component template sounds messy to me. Maybe you should consider using slots to allow content composition instead.
Just in case someone ever wants a work-around/solution to this, I solved it this way:
Before starting your application you should override Vue.prototype.$mount:
import Vue from 'vue';
const mount = Vue.prototype.$mount;
Vue.prototype.$mount = function (el, hydrating) {
const options = this.$options;
if (options.templateOverride && typeof options.templateOverride === 'string' && options.templateOverride.charAt(0) === '#' && document.querySelector(options.templateOverride)) {
let renderFunctions = Vue.compile(document.querySelector(options.templateOverride).innerHTML);
Object.assign(options, renderFunctions);
}
return mount.call(this, el, hydrating);
}
In your vue component now you can say which override x-template should be used if there is any. Example:
<script>
export default {
name: 'hello',
templateOverride: '#hello-override',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
So if Vue finds some x-template in the dom with that override id it will take it. Example:
<div id="app"></div>
<script type="x-template" id="hello-override">
<div id="hello">
<h1>Override: {{ msg }}</h1>
</div>
</script>
<script src="dist/build.js"></script>
That way I can write components in the one component file vue way but also give it away for others to override just the template if needed.
@yyx990803 If I create a pull request for this to make it into the core how are the chances to really make into the core?
Again, the background is this: Working within an agency you have to write applications which can be just included within a website with most of the only some minimal template modifications. Without compiling it again someone else should be able to change the template as the customer needs it.
@dimitri-koenig Thanks for sharing your solution! Since the solution is simple enough and your use case is very specific there's no need to add it to core
@yyx990803, @dimitri-koenig : I also have a similar requirement in which I want to do easy customization where only template modifications are needed. How can i override the templates?
I tried the solution given by @dimitri-koenig but somehomw its not working for me.
@dimitri-koenig : One quick question from the solution. In which file do I need to add the override id. I added the below contents in index.html but it did not work for me. Can you please explain a bit more? I'm relatively new to VueJS.
So if Vue finds some x-template in the dom with that override id it will take it. Example:
<div id="app"></div>
<script type="x-template" id="hello-override">
<div id="hello">
<h1>Override: {{ msg }}</h1>
</div>
</script>
<script src="dist/build.js"></script>
@dimitri-koenig I have tried your solution and it worked, but I've discovered that using extends
is better for my use case.
I am also using a different template for marketing reasons, while the logic stays the same, so I have removed the template from the original component and created two new components that extend the first one, each one with only a template
tag (besides the name
and theextends
keyword which reside in the script
tag): this allows for maximum flexibility without changing the core of the library.
Hope my solution may help other people with a similar use case.
Here is an example:
<script>
export default {
name: 'ProductConfiguration',
computed: {
// computed...
},
methods: {
// methods...
},
// ...other properties
};
</script>
<style lang="scss" scoped>
/* you can include styles here or in the extended component */
</style>
<template>
<div>
<!-- here you define a template -->
</div>
</template>
<script>
import ProductConfiguration from '../ProductConfiguration.vue';
export default {
name: 'ProductLayout',
extends: ProductConfiguration,
// nothing else is needed here
};
</script>
<style lang="scss" scoped>
/* you can include styles here or in the base component */
</style>
If you need a different template (or as many as you want) you just need to create another component that extends the Base Component.
Hi @gtempesta: I'm not sure wether we are taking about the same. In my case I want to load via Githubissues.
Hi
Using components I can provide the template inside the component together with the script code. But as soon as I provide such a template I cannot use the x-template method to override the template. Even writing an own render function which checks for an existing x-template and uses that if found, or else the template inside the component, does not work.
Would be super helpful if there would be a way to override templates explicitly using x-template feature provided within the html file.