Is it possible to use Vue's <component> to conditionally render a component or nothing instead?
For instance, consider the following pattern:
<component :is="hasTooltip ? 'CustomTooltip' : 'div'">
<div>Hover over me!</div>
</component>
In this case, we are rendering a CustomTooltip component when the hasTooltip value is true, otherwise we are rendering a normal div. Is it possible to render a fragment in place of this div( like the <> fragment in React) that will get stripped out in the browser? How might this be accomplished? I'm on Vue 2.0.
Conditionally rendering the component won't work because we want the "Hover over me!" text to render regardless.
Something like this maybe ?
Vue.component('tooltip', {
template: `<div> Tooltip for: <slot></slot> </div>`
})
Vue.component('wrap-if', {
functional: true,
props: ['wrap', 'wrapper'],
render(h, ctx) {
if (ctx.props.wrap) {
return h(ctx.props.wrapper, ctx.data, ctx.children)
} else {
// maybe check that children.length === 1 as Vue 2 does not support fragments
return ctx.children
}
}
})
new Vue({
el: '#app',
data: {
wrap: true
}
})
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
<wrap-if :wrap="wrap" wrapper="tooltip">
<span>This is always rendered no matter what</span>
</wrap-if>
<br>
<button @click="wrap = !wrap">Toggle</button>
<pre>{{$data}}</pre>
</div>
Just consolidating some other comments on this into an answer.
It appears that there's no clean way of conditionally wrapping a component without a plugin in Vue-2, because fragments are not available.
However, this same pattern can be accomplished with either a Vue-2 fragment plugin, or in Vue3, with the use of the fragment component, as in this answer. Instead of rendering the div, render the fragment.