itsncnt
itsncnt

Reputation: 35

How to pass template to grandchild carousel's #slides slot (vue3-carousel)

I need to create a BaseSlider component. in this component, I use vue3-carousel. Here is the BaseSlider code:

<template>
    <div class="mv-slide">
        <carousel ref="carousel" v-model="currentSlide" :items-to-show="1">
            <slot />
            <template #addons v-if="arrow">
                <navigation>
                    <template #next>
                        <span> >> </span>
                    </template>
                    <template #prev>
                        <span>
                            dsa </span>
                    </template>
                </navigation>
            </template>
        </carousel>
        <div class="mv-slide__pagination" v-if="indicator">
            <div v-for="slide in 11" :class="{
                'mv-slide__pagination-item': true,
                'mv-slide__pagination-item--active': currentSlide === slide
            }" @click="currentSlide = slide"></div>
        </div>
    </div>
</template>

Here is how I use the BaseSlider

<BaseSlider>
      <Slide v-for="slide in 10" :key="slide">
                <img src="http://localhost:3000/custom-estimate-mv1.png" alt="custom estimate"
                    class="mv-slide___img">
        </Slide>
 </BaseSlider>

My app is crashed with this code with error

[Vue warn]: Unhandled error during execution of render function at <Carousel ref="carousel" modelValue=0 onUpdate:modelValue=fnonUpdate:modelValue ... >

Cannot set properties of null (setting 'index')

at Array.forEach ()

Does anyone have experience on create component wraping vue3-carousel

Upvotes: 1

Views: 458

Answers (1)

Tolbxela
Tolbxela

Reputation: 5183

If you pass the slides over your BaseSlider component, then your default slot gets a parent Vnode containing all your slides as children.

This means, To access slides you should go over slots.default()[0].children and the Carousel is not prepared for such scenario.

That's why the errors happens in the Carousel at the line

slidesElements.forEach((el, index) => (el.props.index = index));

since the parent Vnode does not have props.

I haven't found any way to fix it using templates, so I wrote a Render Function for the BaseSlider that returns the Carousel and fills the default slot with the slides.

<script setup>
import { useSlots, h} from 'vue';
import { Carousel, Slide, Pagination, Navigation } from 'vue3-carousel';

const slots = useSlots()
const render = () => {
    return  h('div', { class: 'mv-slide' }, [
       h(Carousel, { 'items-to-show': 1 }, {
          default: () => slots.default()[0].children,
          addons: () => [ h(Navigation),  h(Pagination) ]
        })  
    ]);
};
</script>

<template>
    <render />
</template>

Here is the working SFC Playground

Upvotes: 0

Related Questions