Reputation: 3376
I'm writing a component that renders a text. When a word starts with '@' it's a user's reference (like in twitter), and I must create a tooltip with the user's info.
This is how I instantiate the user's info component (this works fine, I'm using it in other places of the app):
const AvatarCtor = Vue.extend(AvatarTooltip);
let avatarComponent = new AvatarCtor({
propsData: {
user: user
}
});
This is the TooltipWrapper component:
<template>
<el-tooltip>
<slot name="content" slot="content"></slot>
<span v-html="text"></span>
</el-tooltip>
</template>
<script>
import {Tooltip} from 'element-ui';
export default {
name: "TooltipWrapper",
components: {
'el-tooltip': Tooltip
},
props: {
text: String
}
}
</script>
And this is how I wire it up all together:
const TooltipCtor = Vue.extend(TooltipWrapper);
const tooltip = new TooltipCtor({
propsData: {
text: "whatever"
}
});
tooltip.$slots.content = [avatarComponent];
tooltip.$mount(link);
This doesn't work. But if I set some random text in the content
slot, it works fine:
tooltip.$slots.content = ['some text'];
So my problem is that I don't know how to pass a component to the slot. What am I doing wrong?
Upvotes: 1
Views: 2473
Reputation: 10729
this.$slots is VNodes, but you assign with one component instance.
Below is one approach (mount the component to one element then reference its vnode) to reach the goal.
Vue.config.productionTip = false
const parentComponent = Vue.component('parent', {
template: `<div>
<div>
<slot name="content"></slot>
<span v-html="text"></span>
</div>
</div>`,
props: {
text: {
type: String,
default: ''
},
}
})
const childComponent = Vue.component('child', {
template: `<div>
<button @click="printSomething()">@<span>{{user}}</span></button>
<h4>You Already @ {{this.clickCount}} times!!!</h4>
</div>`,
props: {
user: {
type: String,
default: ''
},
},
data(){
return {
clickCount: 1
}
},
methods: {
printSomething: function () {
console.log(`already @${this.user} ${this.clickCount} times` )
this.clickCount ++
}
}
})
const TooltipCtor = Vue.extend(parentComponent)
const tooltip = new TooltipCtor({
propsData: {
text: "whatever"
}
})
const SlotContainer = Vue.extend(childComponent)
const slotInstance = new SlotContainer({
propsData: {
user: "one user"
}
})
slotInstance.$mount('#slot')
tooltip.$slots.content = slotInstance._vnode
tooltip.$mount('#link')
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="link">
</div>
<div style="display:none"><div id="slot"></div></div>
Upvotes: 1