I want to use slots in Vue to create a dynamic modal component.
I already tried a lot of tutorials of Vue / slots, but none of them is exactly what i’m looking for.
This is a piece of my modal.vue
:
<template> ... <slot name="modal-body"></slot> ... </template> <script> </script> <style> </style>
This is my javascript compiled file:
import Vue from 'vue'; import modal from './modal.vue'; new Vue({ el: '#modal', render: r => r(modal) });
This is piece of my HTML file:
... <div id="modal"> <template v-slot="modal-body"> <input type="text" id="dynamic-input"> </template> </div> ...
I was expecting that all elements present inside #modal
(#dynamic-input
in this case), were inserted into the slot named modal-body
, inside my Vue element.
Is it possible to do it? Am i missing something?
Advertisement
Answer
Check what version of Vue you are using. The named slot syntax changed in 2.6.0. Consider the differences below. One uses render functions and the other template Strings.
Vue@2.6.10
// Example using template String const modalTemplateString = { template: "<div><div>above</div><slot name="modal-body"></slot><div>below</div></div>" }; const appTemplateString = new Vue({ el: "#appTemplateString", components: { modal: modalTemplateString }, template: "<div><modal><template v-slot:modal-body><div>foobar</div></template></modal></div>" }); // Example using render function const modalRenderFunc = { render(h) { return h("div", [ h("div", "above"), h("div", this.$slots["modal-body"]), h("div", "below") ]); } } const appRenderFunc = new Vue({ el: "#appRenderFunc", components: { modal: modalRenderFunc }, render(h) { return h("div", [ h("modal", [ h("div", { slot: "modal-body" }, "foobar") ]) ]); } });
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <h2>Template String</h2> <div id="appTemplateString"></div> <hr/> <h2>Render Function</h2> <div id="appRenderFunc"></div>
Vue@2.5.22
// Example using template String const modalTemplateString = { template: "<div><div>above</div><slot name="modal-body"></slot><div>below</div></div>" }; const appTemplateString = new Vue({ el: "#appTemplateString", components: { modal: modalTemplateString }, template: "<div><modal><template slot="modal-body"><div>foobar</div></template></modal></div>" }); // Example using render function const modalRenderFunc = { render(h) { return h("div", [ h("div", "above"), h("div", this.$slots["modal-body"]), h("div", "below") ]); } } const appRenderFunc = new Vue({ el: "#appRenderFunc", components: { modal: modalRenderFunc }, render(h) { return h("div", [ h("modal", [ h("div", { slot: "modal-body" }, "foobar") ]) ]); } });
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script> <h2>Template String</h2> <div id="appTemplateString"></div> <hr/> <h2>Render Function</h2> <div id="appRenderFunc"></div>