Is any way to pass a template to extended component? Example, that illustrates the problem:
There is a component named Slide
with a template like so:
If You can change Your source code structure, You should also be able to use jsx. In Vue-Cli3 it requires additional babel plugin, in Nuxt it works out of the box). You simply create some hook function as method or compute, for example:
slotHook () {
return(
<template v-slot.../>
)}
and place it inside the render function. Then, in the child (component extending the default one), You overwrite the slotHook method:
slotHook () {
return (
<template v-slot... some-differen-params:.../>
)}
This approach does not cause any errors/issues during render and works flawless. Other approach might be to use PUG templates and their block & extend functionality. I know I'm posting this response quite late, but maybe it could help somebody.
You have to pass it like this:
<Slide>
//HTML code here goes to slot
</Slide>
(This question is similar to this SO question. I am just gonna share a similar answer I post for that question here.)
The trick is simple. Basically, when extending, create a new component that registers Parent
as a local component.
Demo: https://jsfiddle.net/jacobgoh101/omjgmb3f/
const Slide = Vue.extend({
components: {
Parent
},
template: `
<Parent>
<div style="color:red">I am a slot</div>
</Parent>
`
});
new Slide().$mount('#container')
You can use Vue.compile combined with $createElement
.
const slotTemplate = `<div><h4>This is the slot content</h4>{{message}}</div>`;
const renderer = Vue.compile(slotTemplate)
const slotContent = {
data(){
return {
message: "some data in the slot"
}
},
render: renderer.render,
staticRenderFns: renderer.staticRenderFns
}
const instance = new Slide();
instance.$slots.default = [instance.$createElement(slotContent)];
instance.$mount("#container");
Above is an example of a slot that requires some data. If your slot content is just HTML you could get away with just this:
const slotTemplate = `<div><h4>This is the slot content</h4></div>`
const instance = new Slide();
instance.$slots.default = [instance.$createElement(Vue.compile(slotTemplate))];
instance.$mount("#container");
Here is an example.
Note: $slots[key] should be an array of vNodes. It will render correctly if you use a vNode, but there will be bugs (e.g. when calling vm._update)
If you are open to change your approach a little bit, a <component>
instead of <slot>
:
https://jsfiddle.net/jonataswalker/z5Lgbjv8/
const Parent = {
template: `<div>
<span>parent content</span>
<component :is="view"></component>
</div>`,
data() {
return { view: '' }
}
}
const Other = {
template: `<div>
<h1>from Other</h1>
</div>`
}
const Slide = Vue.extend(Parent)
// how to pass template to the Parent`s slot?
new Slide({
data: { view: Other }
}).$mount('#container')