Reputation: 888
Hi everybody, please pardon my english :-)
I have a Vue component that can take dynamic slots (the names of the slots will depend on a props).
I use it on several places and some of the slots are always present.
To avoid redundancy, I'm looking for a way to create a component that "wrap" the final component to allow me to define only the additionals slots.
If there is an "obvious" way to achieve it, I may have missed it :-)
<b-table
show-empty
small
hover
[...some others and always present props...]
:items="aDataVarThatWillChangeBasedOnTheContext"
[...some others and uniq props...]
>
<template slot="same-1">
A slot that will always be present with the same content (for example, a checkbox in the first column)
</template>
<template slot="same-2">
A slot that will always be present with the same content (for example, some action buttons in the last column)
</template>
[...some others and always present slots...]
<template slot="not-the-same">
A slot that is only used in this context (for example, a duration based on a row timestamp and a timestamp picked by the user)
</template>
[...some others and uniq slots...]
</b-table>
<my-b-table
:items="aDataVarThatWillChangeBasedOnTheContext"
>
<template slot="not-the-same">
A slot that is only used in this context (for example, a duration based on a row timestamp and a timestamp picked by the user)
</template>
</my-b-table>
Note: The dynamic slot name is not predictible. If I suddenly need a "foo" column, I should be able to pass a "foo" slot (and a "HEAD_foo" slot, in my case)
I read here that:
They’re (the functionnal components) also very useful as wrapper components. For example, when you need to:
- Programmatically choose one of several other components to delegate to
- Manipulate children, props, or data before passing them on to a child component
And "Manipulate children, props, or data before passing them on to a child component" seems to be exactly what I need.
I looked on render function but a lot of things seems to be not implemented, like the v-model, and I have difficulties to figure out how to pass dynamic slots...
Thank you in advance for your(s) answer(s) !
up: At the 07.03.2018 I still dont have any idea about how to solve this case
Upvotes: 2
Views: 5161
Reputation: 888
Found the answer that was somehow unclear to me that month ago.
("Dynamic" means here "not explicitely declared by the component, but gived by the parent")
Props and scoped slots can be gived dynamically by the options
object of createElement
function.
"Simple" Slots can be gived dynamically by the childs
array of createElement
function.
Props can't be dynamic unless the component is functional.
Slots can always be retrieved dynamically.
Scoped slots can be retrieved only if the component isn't functional.
It's not possible to have dynamics props and scoped slots at the same time...
But it's possible to declare all the needed props and then to use a "non-functionnal" component as wrapper and as wrapped.
var component = Vue.component('component-name', {
props: ['name', 'of', 'the', 'props'],
// [...]
aMethod: function () {
this._props // all the declared props
this.$slots // all the slots
this.$scopedSlots // all the scoped slots
}
});
var component = Vue.component('component-name', {
functional: true,
render: function (createElement, context) {
context.props // all the props
context.children // all the slots as an array
context.slots() // all the slots as an object
}
});
var component = Vue.component('component-name', {
render: function (createElement) {
return createElement(
childComponent,
{
props: propsToGive,
scopedSlots: scopedSlotsToGive
},
[
// non-scoped slots to give
createElement('slot-tag-name', {slot: 'slot-name'})
]
);
}
});
https://v2.vuejs.org/v2/guide/render-function.html
https://v2.vuejs.org/v2/guide/render-function.html#createElement-Arguments
https://v2.vuejs.org/v2/guide/render-function.html#Functional-Components
https://jsfiddle.net/5umk7p52/
Upvotes: 2
Reputation: 55634
Just make a regular component out of your customized <b-table>
.
You'll need to define an items
prop for your component to pass as the items
for the <b-table>
component.
And, to define a slot
for your component, you'll need to use the <slot>
tag, specifying the name using the name
attribute.
If you'd like to make one of the slots from the <b-table>
component accessible in the <my-b-table>
component, simply pass a <slot>
tag as the content of the slot in your custom component.
It would look something like this:
Vue.component('my-b-table', {
template: `
<b-table
show-empty
small
hover
:items="items"
>
<template slot="same-1">
Content to pass to the b-table's slot
</template>
<slot name="not-the-same">
A slot that is only used in this context
</slot>
<template slot="last_edit">
<slot name="last_edit">
A slot to pass content to the b-table component's slot
</slot>
</template>
</b-table>
`,
props: { items: Array },
});
Upvotes: 0