2
<template>
    <div class="carousel">
        
        <slot></slot>
         <button @click="index++">Next</button>
    </div>

</template>
<script setup>
import { useSlots, onMounted, onUpdated, ref} from 'vue';

const slots = useSlots()
const index = ref(0)
onMounted(() => {
  const defaultSlotElements = slots.default()
  console.log(`My default slot has ${defaultSlotElements.length} elements.`)
  
}),
onUpdated(() =>{
    console.log(defaultSlotElements[index])
}
)

</script>

I'm trying to create carousel based on slots. Thanks to the previous person on stack overflow, he helped me to figured out how to extract array of slots. Now, I'm dealing with another issue. In order to create carousel, I have to somehow change index of element in the array, so I can move to the next slide of my carousel. Later I have to inject it to my slide component to let V-show render current slot that is 0 by default. But index's value is changed by v-on directive that changes index, so it selects the next or previous slot in the array. I know that I've chosen a complex subject in vue but I don't want to use simpler version of carousel based on images' array because I can't add another component inside this one.

It turned out that I cannot simply by changing index arr[index] select the next object in the array.

Akirambur
  • 75
  • 6

1 Answers1

1

If you really need to do it with slots, then you will have to do it with Vue Render Functions & JSX

<script setup>
import { useSlots, onMounted, onUpdated, ref, h} from 'vue';

const slots = useSlots()
const index = ref(0)
const current = ref(null)
onMounted(() => {
  const defaultSlotElements = slots.default()
  current.value = defaultSlotElements[0]
}),
onUpdated(() =>{
    console.log(defaultSlotElements[index])
    }
)  
const render = () => {
    return h('div', { class: 'carousel'}, [
    h('p', `My default slot has ${slots.default().length} elements.`),
    h('div', slots.default()[index.value]),
    h('p', `Picture ${ index.value + 1 }`),
    h('button', { onClick: () => { 
      index.value = index.value + 1 == slots.default().length ? 0 : index.value + 1
    } }, 'Next')
  ]);
};
</script>

<template>
    <render />
</template>

Here is the working SFC Playground

UPDATE

The render function does work with custom components.

Here is an attempt to build up your <Carousel><Slide><Lightbox></Lightbox></Slide></Carousel structure.

SFC Playground

I don't see any other way to build what you want using the default slot and not using a render function.

Tolbxela
  • 4,767
  • 3
  • 21
  • 42
  • I really apologies for inconvenience but I explained that it has to have a different template. You've done a great job but it has one issue. It's not that I've been telling about. ` – Akirambur Feb 22 '23 at 15:45
  • No problem :-) Then explain please your "different template". Show the other side, what do you want to put in the slots. – Tolbxela Feb 22 '23 at 15:50
  • Btw, this solution will work independent from what you are trying to put in your slots. – Tolbxela Feb 22 '23 at 15:56
  • Each slot is the slide in this template. What do I want? I want to provide a value of current slide into my slot slide and then inject it to make possible render it with v-show like `v-show="index == currentSlide"` Your code is way too complex solution and it doesn't provide a function of adding another component inside this one. I want to add my Lightbox inside slide like `` And this lightbox allows me to open an image in carousel in image gallery – Akirambur Feb 22 '23 at 16:01
  • I also think that I have to understand the code I'm going to use. This is why I want to use a different approach which I've already seen on youtube channel "LearnVue" because I understand. But I've never tried using vnodes, so It's a bit too early to dive into this feature of vue – Akirambur Feb 22 '23 at 16:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252057/discussion-between-akirambur-and-tolbxela). – Akirambur Feb 22 '23 at 17:31