I'm trying to create a reusable component for iterating over items, filtering them, and adding some classes to the slot (if the item is even, odd, first, last etc..)
Here's my reusable component:
<template>
<ul :class="classes">
<slot
v-for="(item, index) in filteredItems"
:item="item"
:class="{
'first': index == 0,
'odd': !(index % 2),
'even': index % 2,
'last': index == (filteredItems.length - 1)
}"
>
</slot>
</ul>
</template>
<script>
export default {
props: ['items', 'classes'],
data() {
return {
filteredItems: this.items.filter(item => item.active)
};
}
};
</script>
And here's how I use it:
<component-list :classes="'some-class'" :items="category.products">
<template scope="props">
<product :product="props.item"></product>
</template>
<component-list>
Everything works as expected, but it doesn't add classes to the element put inside .
Am I doing anything wrong? Is it even technically possible in Vue.js 2 to do something like this?
Thanks for any help or suggestion!
Scoped slots To pass a property in Vue, you would define the data in the parent component and assign a value to the data. Then, you'd pass the value of the property to the child component so the data becomes a property in the child component.
Also note that the fallback text of “Text In Slots Example” is replaced entirely. So in the most basic sense when you want to use slots in VueJS, you add the <slot></slot> tags in the child component where you expect to receive data from outside.
Vue is also perfectly capable of powering sophisticated Single-Page Applications in combination with modern tooling and supporting libraries. The v-model directive makes two-way binding between a form input and app state very easy to implement.
Here is how you can use the array syntax to dynamically bind and toggle the class. Try changing the value of property isActive from developer console or using the VueJS Dev Tools, and see text toggling between green and red and it dynamically switches the class that is attached to it.
With vuejs2
styling from slots has been removed as stated here:
Content inserted via named no longer preserves the slot attribute. Use a wrapper element to style them, or for advanced use cases, modify the inserted content programmatically using render functions.
So simplest thing as suggested will be to use a wrapper element as following:
<template>
<ul :class="classes">
<slot>
<div
v-for="(item, index) in filteredItems"
:item="item"
:class="{
'first': index == 0,
'odd': !(index % 2),
'even': index % 2,
'last': index == (filteredItems.length - 1)
}"
>
</div>
</slot>
</ul>
</template>
I have another way can get your aim, but not use render
, still use slot
.
The reusable component:
<template>
<ul :class="classes">
<slot
v-for="(item, index) in filteredItems"
:item="item"
:_class="{
'first': index == 0,
'odd': !(index % 2),
'even': index % 2,
'last': index == (filteredItems.length - 1)
}"
>
</slot>
</ul>
</template>
<script>
export default {
props: ['items', 'classes'],
data() {
return {
filteredItems: this.items.filter(item => item.active)
};
}
};
</script>
use _class
to class
keyword, so Vue.js
will let _class
as the common property.
Then in your use:
<component-list :classes="'some-class'" :items="category.products">
<template scope="{ item, _class }">
<product :product="item" :class="_class"></product>
</template>
<component-list>
By the scope property, your can still get _class
from slot.
After all, use render
may be more conciseness. :)
In your child component don't use the slot tag, just bind the slot data to a normal element.
For example say I have a component called modal. In my parent I have this:
<modal>
<h1 slot="title">My modal title</h1>
</modal>
So with normal slot use my child component would have the following markup:
<slot name="title" class="this-class-will-not-get-added"></slot>
But that class will not get added.
So instead we can do this:
<h1 class="this-class-will-get-added">{{this.$slots.title['0'].children['0'].text}}</h1>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With