1

I'm using vue-flickity for a carousel. There's a <flickity /> component (the carousel), a <p> tag with data {{ selectedIndex }}, and a button which gets the current slide number from flickity, and updates selectedIndex.

How can I automatically update selectedIndex with the current slide index when a user scrolls left or right (i.e. calls Next/Previous methods)? I'm struggling to "hook into" those methods of the module.

I can define a method Next() and bind that to a button, but it doesn't update when a user scrolls.

EDIT: I've managed to hook into on.change (using mounted). console.log shows me the correct selectedInde now, but this isn't reacting down to where it says "You are at Slide number {{ selectedIndex }}"

<template>
  <div>
    <flickity ref="flickity" :options="flickityOptions">
      <div class="carousel-cell">1</div>
      <div class="carousel-cell">2</div>
      <div class="carousel-cell">3</div>
      <div class="carousel-cell">4</div>
      <div class="carousel-cell">5</div>
    </flickity>
    <p>You are at Slide number {{ selectedIndex }}</p>
    <button @click="manualUpdate()">Update</button>
  </div>
</template>

<script>
import Flickity from 'vue-flickity'

export default {
  components: {
    Flickity
  },
  data() {
    return {
      flickityOptions: {
        initialIndex: 0,
        prevNextButtons: false,
        pageDots: false,
        wrapAround: true
      },
      selectedIndex: 0
    }
  },
  methods: {
    manualUpdate() {
      this.selectedIndex = this.$refs.flickity.selectedIndex();
      console.log(this.selectedIndex)
    },
  },
  mounted() {
    this.$refs.flickity.on('change', function (event) {
      this.selectedIndex = event
      console.log(this.selectedIndex)
    })
  }
}
</script>

<style>
/* external css: flickity.css */

* {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

.carousel-cell {
  width: 80%;
  min-height: 50vh;
  max-height: 80vh;
  object-fit: contain;
  margin-right: 10px;
}
</style>
ron_g
  • 1,474
  • 2
  • 21
  • 39
  • Can you please double check that `manualUpdate` is being called with a `console.log`? Also, in your devtools you should see some events emitted by flickity, wiring it on a listener `@yourCoolEvent` could fix this issue by calling a method on the emitted listener. Since `$refs` are not reactive in Vue2. – kissu Sep 28 '21 at 10:25
  • @kissu yes, confirmed `manualUpdate` works via `console.log`. I don't see any events firing when I change slide. – ron_g Sep 28 '21 at 10:36
  • No way, there should be some events firing since it's a vue package. Can you make a [repro] please? – kissu Sep 28 '21 at 10:38
  • @kissu I have updated it with the minimal reproducible example. You need the module https://www.npmjs.com/package/vue-flickity of course – ron_g Sep 28 '21 at 10:59
  • @kissu using `mounted`, I've managed to hook into it. It now `console.log`s the slide index, but it's not updating the template. Any ideas? – ron_g Sep 28 '21 at 12:38

1 Answers1

1

As explain on this Github issue, you need to bind the listener on the init event.
The end result looks like this:

<template>
  <div>
    <flickity ref="flickity" :options="flickityOptions" @init="onInit">
      <div class="carousel-cell">1</div>
      <div class="carousel-cell">2</div>
      <div class="carousel-cell">3</div>
      <div class="carousel-cell">4</div>
      <div class="carousel-cell">5</div>
    </flickity>
    <p>You are at Slide number {{ selectedIndex }}</p>
    <button @click="goToPrevious">Previous</button>
    <button @click="goToNext">Next</button>
  </div>
</template>

<script>
import Flickity from 'vue-flickity'

export default {
  components: {
    Flickity,
  },
  data() {
    return {
      flickityOptions: {
        initialIndex: 0,
        prevNextButtons: false,
        pageDots: false,
        wrapAround: true,
      },
      selectedIndex: 0,
    }
  },
  methods: {
    goToNext() {
      this.$refs.flickity.next()
    },
    goToPrevious() {
      this.$refs.flickity.previous()
    },
    onInit() {
      this.$refs.flickity.on('change', (event) => {
        this.selectedIndex = event
        console.log('current index', event)
      })
    },
  },
}
</script>

<style>
/* external css: flickity.css */

* {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

.carousel-cell {
  width: 80%;
  min-height: 50vh;
  max-height: 80vh;
  object-fit: contain;
  margin-right: 10px;
}
</style>

There was indeed no other event, which is super strange and I took the libery to write previous/next buttons rather than keep something manual but you could compute and offset (did not found any method for a direct setter).

kissu
  • 40,416
  • 14
  • 65
  • 133
  • 1
    Thank you for taking the time. In the end, I used vue-awesome-swiper. I can pass my method (to update data) directly into the component. – ron_g Sep 30 '21 at 13:40