Vuejs nested slots: how to pass slot to grandchild












1














I use different vuetify components, for example v-menu. It has a template like this:



<v-menu>
<a slot="activator">menu</a>
<v-list>
<v-list-tile>Menu Entry 1</v-list-tile>
<v-list-tile>Menu Entry 2</v-list-tile>
</v-list>
</v-menu>


Suppose I want to add another wrapper around it. That is my special menu component that has some predefined menu options. And I want it to has an activator slot as well. And the last should be somehow assigned to the original v-menu activator slot. Is it possible?



Example:



// index.vue: 
<template>
<my-special-menu>
<button>My special menu trigger</button>
</my-special-menu>
</template>

// MySpecialMenu.vue
<template>
<v-menu>
<slot slot="activator"/> <-- I don't know how to write this line
<v-list>...</v-list>
</v-menu>
</template>


<slot slot="activator"> is an incorrect equation. The goal is to pull the content from the parent (that is <button>..</button> in the example), and use it as slot="activator" in v-menu.



I can write it like this:



<v-menu>
<a slot="activator"><slot/></a>
...
</v-menu>


But this case the result template will be:



<div class="v-menu__activator">
<a>
<button>My special menu trigger</button>
</a>
</div>


That's not exactly what I want. Is it possible to get rid off <a> wrapper here?



Update:
We can use a construction like <template slot="activator"><slot name="activator"/></template> to throw some slot to a grand child. But what if we have multiple slots and we want to proxy them all? That's like inheritAttrs and v-bind="$attrs" for slots. Is it currently possible?



For example, there's <v-autocomplete> component in vuetify that has append, prepend, label, no-data, progress, item, selection etc slots. I write some wrapper component around this, it currently looks like:



<template>
<v-autocomplete ..>
<template slot="append"><slot name="append"/></template>
<template slot="prepend"><slot name="prepend"/></template>
<template slot="label"><slot name="label"/></template>
...
<template slot="item" slot-scope="props"><slot name="item" v-bind="props"/></template>
</v-autocomplete>
</template>


Is it possible to avoid all slots enumeration here?










share|improve this question
























  • attribute name instead of slot so: <slot name="activator">
    – Traxo
    Nov 22 at 13:05
















1














I use different vuetify components, for example v-menu. It has a template like this:



<v-menu>
<a slot="activator">menu</a>
<v-list>
<v-list-tile>Menu Entry 1</v-list-tile>
<v-list-tile>Menu Entry 2</v-list-tile>
</v-list>
</v-menu>


Suppose I want to add another wrapper around it. That is my special menu component that has some predefined menu options. And I want it to has an activator slot as well. And the last should be somehow assigned to the original v-menu activator slot. Is it possible?



Example:



// index.vue: 
<template>
<my-special-menu>
<button>My special menu trigger</button>
</my-special-menu>
</template>

// MySpecialMenu.vue
<template>
<v-menu>
<slot slot="activator"/> <-- I don't know how to write this line
<v-list>...</v-list>
</v-menu>
</template>


<slot slot="activator"> is an incorrect equation. The goal is to pull the content from the parent (that is <button>..</button> in the example), and use it as slot="activator" in v-menu.



I can write it like this:



<v-menu>
<a slot="activator"><slot/></a>
...
</v-menu>


But this case the result template will be:



<div class="v-menu__activator">
<a>
<button>My special menu trigger</button>
</a>
</div>


That's not exactly what I want. Is it possible to get rid off <a> wrapper here?



Update:
We can use a construction like <template slot="activator"><slot name="activator"/></template> to throw some slot to a grand child. But what if we have multiple slots and we want to proxy them all? That's like inheritAttrs and v-bind="$attrs" for slots. Is it currently possible?



For example, there's <v-autocomplete> component in vuetify that has append, prepend, label, no-data, progress, item, selection etc slots. I write some wrapper component around this, it currently looks like:



<template>
<v-autocomplete ..>
<template slot="append"><slot name="append"/></template>
<template slot="prepend"><slot name="prepend"/></template>
<template slot="label"><slot name="label"/></template>
...
<template slot="item" slot-scope="props"><slot name="item" v-bind="props"/></template>
</v-autocomplete>
</template>


Is it possible to avoid all slots enumeration here?










share|improve this question
























  • attribute name instead of slot so: <slot name="activator">
    – Traxo
    Nov 22 at 13:05














1












1








1







I use different vuetify components, for example v-menu. It has a template like this:



<v-menu>
<a slot="activator">menu</a>
<v-list>
<v-list-tile>Menu Entry 1</v-list-tile>
<v-list-tile>Menu Entry 2</v-list-tile>
</v-list>
</v-menu>


Suppose I want to add another wrapper around it. That is my special menu component that has some predefined menu options. And I want it to has an activator slot as well. And the last should be somehow assigned to the original v-menu activator slot. Is it possible?



Example:



// index.vue: 
<template>
<my-special-menu>
<button>My special menu trigger</button>
</my-special-menu>
</template>

// MySpecialMenu.vue
<template>
<v-menu>
<slot slot="activator"/> <-- I don't know how to write this line
<v-list>...</v-list>
</v-menu>
</template>


<slot slot="activator"> is an incorrect equation. The goal is to pull the content from the parent (that is <button>..</button> in the example), and use it as slot="activator" in v-menu.



I can write it like this:



<v-menu>
<a slot="activator"><slot/></a>
...
</v-menu>


But this case the result template will be:



<div class="v-menu__activator">
<a>
<button>My special menu trigger</button>
</a>
</div>


That's not exactly what I want. Is it possible to get rid off <a> wrapper here?



Update:
We can use a construction like <template slot="activator"><slot name="activator"/></template> to throw some slot to a grand child. But what if we have multiple slots and we want to proxy them all? That's like inheritAttrs and v-bind="$attrs" for slots. Is it currently possible?



For example, there's <v-autocomplete> component in vuetify that has append, prepend, label, no-data, progress, item, selection etc slots. I write some wrapper component around this, it currently looks like:



<template>
<v-autocomplete ..>
<template slot="append"><slot name="append"/></template>
<template slot="prepend"><slot name="prepend"/></template>
<template slot="label"><slot name="label"/></template>
...
<template slot="item" slot-scope="props"><slot name="item" v-bind="props"/></template>
</v-autocomplete>
</template>


Is it possible to avoid all slots enumeration here?










share|improve this question















I use different vuetify components, for example v-menu. It has a template like this:



<v-menu>
<a slot="activator">menu</a>
<v-list>
<v-list-tile>Menu Entry 1</v-list-tile>
<v-list-tile>Menu Entry 2</v-list-tile>
</v-list>
</v-menu>


Suppose I want to add another wrapper around it. That is my special menu component that has some predefined menu options. And I want it to has an activator slot as well. And the last should be somehow assigned to the original v-menu activator slot. Is it possible?



Example:



// index.vue: 
<template>
<my-special-menu>
<button>My special menu trigger</button>
</my-special-menu>
</template>

// MySpecialMenu.vue
<template>
<v-menu>
<slot slot="activator"/> <-- I don't know how to write this line
<v-list>...</v-list>
</v-menu>
</template>


<slot slot="activator"> is an incorrect equation. The goal is to pull the content from the parent (that is <button>..</button> in the example), and use it as slot="activator" in v-menu.



I can write it like this:



<v-menu>
<a slot="activator"><slot/></a>
...
</v-menu>


But this case the result template will be:



<div class="v-menu__activator">
<a>
<button>My special menu trigger</button>
</a>
</div>


That's not exactly what I want. Is it possible to get rid off <a> wrapper here?



Update:
We can use a construction like <template slot="activator"><slot name="activator"/></template> to throw some slot to a grand child. But what if we have multiple slots and we want to proxy them all? That's like inheritAttrs and v-bind="$attrs" for slots. Is it currently possible?



For example, there's <v-autocomplete> component in vuetify that has append, prepend, label, no-data, progress, item, selection etc slots. I write some wrapper component around this, it currently looks like:



<template>
<v-autocomplete ..>
<template slot="append"><slot name="append"/></template>
<template slot="prepend"><slot name="prepend"/></template>
<template slot="label"><slot name="label"/></template>
...
<template slot="item" slot-scope="props"><slot name="item" v-bind="props"/></template>
</v-autocomplete>
</template>


Is it possible to avoid all slots enumeration here?







vue.js vuejs2 vuetify.js






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 at 11:55

























asked Nov 22 at 12:10









Kasheftin

94521233




94521233












  • attribute name instead of slot so: <slot name="activator">
    – Traxo
    Nov 22 at 13:05


















  • attribute name instead of slot so: <slot name="activator">
    – Traxo
    Nov 22 at 13:05
















attribute name instead of slot so: <slot name="activator">
– Traxo
Nov 22 at 13:05




attribute name instead of slot so: <slot name="activator">
– Traxo
Nov 22 at 13:05












1 Answer
1






active

oldest

votes


















2














If you put the slot attribute on a html element, that html element is passed to the child component to fill the slot with that name. If you don't want to pass along a html element, you can use slot on a template tag within your component. A template tag groups elements, but does not render to a html element, which is perfect here. You can use template tags also for other things, such as to group elements in a v-if for example, or to repeat multiple elements with a v-for.



// App.vue
<template>
<div id="app">
<test>
<template slot="activator">
Click <b>me</b>!
</template>
</test>
</div>
</template>




// Test.vue
<template>
<div class="wrapper">
<grand-child>
<template slot="activator">
<slot name="activator"></slot>
</template>
</grand-child>

This is some text
</div>
</template>




// GrandChild.vue
<template>
<div>
<a href="#" @click="toggle = !toggle">
<slot name="activator">Default</slot>
</a>

<div v-if="toggle">This appears and disappears</div>
</div>
</template>


Edit Vue Template



Edit: If you want to do this for arbitrary slots, this is also possible. this.$slots contains the slots and their content, so with something like the following, you can pass the slot content to a slot with the same name:



<grand-child>
<template v-for="(_, slot) in $slots">
<template :slot="slot">
<slot :name="slot"></slot>
</template>
</template>
</grand-child>


Edit Vue Template






share|improve this answer























  • Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
    – Kasheftin
    Nov 28 at 11:46













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53430731%2fvuejs-nested-slots-how-to-pass-slot-to-grandchild%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














If you put the slot attribute on a html element, that html element is passed to the child component to fill the slot with that name. If you don't want to pass along a html element, you can use slot on a template tag within your component. A template tag groups elements, but does not render to a html element, which is perfect here. You can use template tags also for other things, such as to group elements in a v-if for example, or to repeat multiple elements with a v-for.



// App.vue
<template>
<div id="app">
<test>
<template slot="activator">
Click <b>me</b>!
</template>
</test>
</div>
</template>




// Test.vue
<template>
<div class="wrapper">
<grand-child>
<template slot="activator">
<slot name="activator"></slot>
</template>
</grand-child>

This is some text
</div>
</template>




// GrandChild.vue
<template>
<div>
<a href="#" @click="toggle = !toggle">
<slot name="activator">Default</slot>
</a>

<div v-if="toggle">This appears and disappears</div>
</div>
</template>


Edit Vue Template



Edit: If you want to do this for arbitrary slots, this is also possible. this.$slots contains the slots and their content, so with something like the following, you can pass the slot content to a slot with the same name:



<grand-child>
<template v-for="(_, slot) in $slots">
<template :slot="slot">
<slot :name="slot"></slot>
</template>
</template>
</grand-child>


Edit Vue Template






share|improve this answer























  • Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
    – Kasheftin
    Nov 28 at 11:46


















2














If you put the slot attribute on a html element, that html element is passed to the child component to fill the slot with that name. If you don't want to pass along a html element, you can use slot on a template tag within your component. A template tag groups elements, but does not render to a html element, which is perfect here. You can use template tags also for other things, such as to group elements in a v-if for example, or to repeat multiple elements with a v-for.



// App.vue
<template>
<div id="app">
<test>
<template slot="activator">
Click <b>me</b>!
</template>
</test>
</div>
</template>




// Test.vue
<template>
<div class="wrapper">
<grand-child>
<template slot="activator">
<slot name="activator"></slot>
</template>
</grand-child>

This is some text
</div>
</template>




// GrandChild.vue
<template>
<div>
<a href="#" @click="toggle = !toggle">
<slot name="activator">Default</slot>
</a>

<div v-if="toggle">This appears and disappears</div>
</div>
</template>


Edit Vue Template



Edit: If you want to do this for arbitrary slots, this is also possible. this.$slots contains the slots and their content, so with something like the following, you can pass the slot content to a slot with the same name:



<grand-child>
<template v-for="(_, slot) in $slots">
<template :slot="slot">
<slot :name="slot"></slot>
</template>
</template>
</grand-child>


Edit Vue Template






share|improve this answer























  • Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
    – Kasheftin
    Nov 28 at 11:46
















2












2








2






If you put the slot attribute on a html element, that html element is passed to the child component to fill the slot with that name. If you don't want to pass along a html element, you can use slot on a template tag within your component. A template tag groups elements, but does not render to a html element, which is perfect here. You can use template tags also for other things, such as to group elements in a v-if for example, or to repeat multiple elements with a v-for.



// App.vue
<template>
<div id="app">
<test>
<template slot="activator">
Click <b>me</b>!
</template>
</test>
</div>
</template>




// Test.vue
<template>
<div class="wrapper">
<grand-child>
<template slot="activator">
<slot name="activator"></slot>
</template>
</grand-child>

This is some text
</div>
</template>




// GrandChild.vue
<template>
<div>
<a href="#" @click="toggle = !toggle">
<slot name="activator">Default</slot>
</a>

<div v-if="toggle">This appears and disappears</div>
</div>
</template>


Edit Vue Template



Edit: If you want to do this for arbitrary slots, this is also possible. this.$slots contains the slots and their content, so with something like the following, you can pass the slot content to a slot with the same name:



<grand-child>
<template v-for="(_, slot) in $slots">
<template :slot="slot">
<slot :name="slot"></slot>
</template>
</template>
</grand-child>


Edit Vue Template






share|improve this answer














If you put the slot attribute on a html element, that html element is passed to the child component to fill the slot with that name. If you don't want to pass along a html element, you can use slot on a template tag within your component. A template tag groups elements, but does not render to a html element, which is perfect here. You can use template tags also for other things, such as to group elements in a v-if for example, or to repeat multiple elements with a v-for.



// App.vue
<template>
<div id="app">
<test>
<template slot="activator">
Click <b>me</b>!
</template>
</test>
</div>
</template>




// Test.vue
<template>
<div class="wrapper">
<grand-child>
<template slot="activator">
<slot name="activator"></slot>
</template>
</grand-child>

This is some text
</div>
</template>




// GrandChild.vue
<template>
<div>
<a href="#" @click="toggle = !toggle">
<slot name="activator">Default</slot>
</a>

<div v-if="toggle">This appears and disappears</div>
</div>
</template>


Edit Vue Template



Edit: If you want to do this for arbitrary slots, this is also possible. this.$slots contains the slots and their content, so with something like the following, you can pass the slot content to a slot with the same name:



<grand-child>
<template v-for="(_, slot) in $slots">
<template :slot="slot">
<slot :name="slot"></slot>
</template>
</template>
</grand-child>


Edit Vue Template







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 28 at 18:02

























answered Nov 22 at 12:40









Sumurai8

12.9k83160




12.9k83160












  • Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
    – Kasheftin
    Nov 28 at 11:46




















  • Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
    – Kasheftin
    Nov 28 at 11:46


















Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
– Kasheftin
Nov 28 at 11:46






Thanks, the <template slot="activator"><slot name="activator"/></template> construction works just fine. Do you think it's possible to inherit all slots (like we have inheritAttrs and a possibility to use v-bind="$attrs")? I updated the question.
– Kasheftin
Nov 28 at 11:46




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53430731%2fvuejs-nested-slots-how-to-pass-slot-to-grandchild%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Sphinx de Gizeh

Dijon

Équipe cycliste