javascriptvue.jsvuejs2flickity

VanillaJS to VueJS Error: bad element for Flickity: carousel


I'm trying to get this Flickity example (CodePen) to work in a VueJS component.

HTML

<div class="carousel">
  <div class="carousel-cell"></div>
  <div class="carousel-cell"></div>
  <div class="carousel-cell"></div>
  <div class="carousel-cell"></div>
  <div class="carousel-cell"></div>
</div>

JS

 var flkty = new Flickity('.carousel');

    flkty.on( 'dragStart', function() {
      console.log('dragStart');
    });

I get this error:

bad element for Flickity: carousel

My not working version:

JS data ()

import Flickity from 'flickity'
var flkty = new Flickity('.carousel')
export default {
  data () {
    return {
      flickityOptions: {
        dragThreshold: 50,
        initialIndex: 1,
        prevNextButtons: false,
        pageDots: false,
        wrapAround: false,
        hash: true,
        percentPosition: false
      },

JS mounted ()

  mounted () {
    flkty.on('dragStart', function () {
      this.stageDragging = true
      console.log('stageDragging: ' + this.stageDragging)
    })
    flkty.on('dragEnd', function () {
      this.stageDragging = false
      console.log('stageDragging: ' + this.stageDragging)
    })

How to use this Flickity example in a VueJS component?


Solution

  • In your <script> section, the JavaScript executes before the template has been rendered in the document, so Flickity wouldn't be able to find .carousel if called outside a hook. Vue instances have a mounted() lifecycle hook that gets called when its template has rendered, which is where you should create the Flickity carousel:

    // const flkty = new Flickity(...) // DON'T DO THIS HERE
    export default {
      mounted() {
        this.$nextTick(() => {
          const flkty = new Flickity(...)
          // ...
        });
      }
    }
    

    Also, instead of passing the .carousel classname to Flickity, pass a ref to the .carousel element in order to avoid grabbing an unexpected .carousel element in the document (e.g., if you had multiple component instances).

    // template
    <div ref="carousel">
    
    // script
    new Flickity(this.$refs.carousel)
    

    demo