drewjbartlett / vue-flickity

A Vue Slider / Carousel Component for Flickity.js
http://drewjbartlett.com/demos/vue-flickity/
374 stars 55 forks source link

Not working on first render when using custom components with v-for #32

Open freshlySqueezedBananas opened 6 years ago

freshlySqueezedBananas commented 6 years ago

Hi,

Similarly with @angelorc's issue when using a custom component with v-for, the slides are rendered outside flickity's viewport. Tried the solution @exxy provided to no avail.

This doesn't work

<flickity v-if="Object.keys(components).length > 0" ref="flickity" :options="flickityOptions">
      <picker-slide v-for="(item, index) in components" :key="index"
                            :name="index"
                            :item="item"/>
  </flickity>

This works

<flickity v-if="Object.keys(components).length > 0" ref="flickity" :options="flickityOptions">
      <div class="carousel-cell" v-for="(item, index) in components" :key="index"
                            :name="index"
                            :item="item">
        {{ item.name }}
      </div>
  </flickity>

The weird thing is, it only won't work on first render. If I return back to the page where the flickity slider is, it's rendered nicely. Same behaviour when using custom components inside the div on the 2nd method. On first render they will render weirdly, and when I return to that page. it's all rendered as intended.

drewjbartlett commented 6 years ago

@freshlySqueezedBananas could you provide me with a codepen example?

pmochine commented 6 years ago

Same problem for me. Just don't have the time for a codepen sorry.

But I used:

<flickity ref="flickity" :options="flickityOptions" v-if="windowWidth < 768">

                <destinations-list 
                    v-for="(list, index) in lists" 
                    :key="index" 
                    :list="list"
                    :class="'blog-container'"></destinations-list>
            </flickity>

With destinations-list.vue

 <template>
<div class="p-2">
    <a 
    :href="/test">
        <div class="blog-card box-shadow-none rounded-0" :class="location">

            <div class="title-content">
                <h5 class="osans text-uppercase">{{ list[0] }}</h5>
                <hr />
                <div class="intro bfont"><em>{{ list[1] }}</em></div>
            </div>

            <div class="card-info bfont">
                <div>
                {{ list[2] }}
                </div> 
            </div>

            <div class="gradient-overlay"></div>
            <div class="color-overlay"></div>
        </div>
    </a>
</div>
</template>

It doesn't work. The divs are not inside of the slider...

drewjbartlett commented 6 years ago

hmmm maybe a scoped slot could solve this? Now that I know the issue I can attempt to fix :D Thanks!

josh9060 commented 6 years ago

I've been looking into this issue - can't seem to find a fix. Any updates?

UPDATE:

It seems that setting lazy-load to true and using the "data-flickity-lazyload" as the default src option fixes this problem.

edtownend commented 6 years ago

As a fix I'd suggest wrapping the new Flickity call inside the init method in a this.$nextTick. Happy to make a PR if needed.

Rrrafau commented 6 years ago

Experiencing same issue here.

@edtownend what do you mean by "flickity call", can you please elaborate?

In the parent component I've tried doing:

mounted() {
    this.$nextTick(function() {
        this.$refs.flickity.rerender()
    })
}

But that doesn't always work. Wrapping rerender call in a timeout of like 100ms seems to be fixing it for me but that's a very hacky solution

edtownend commented 6 years ago

I think the reason that's not working for you is that at the time the parent component is mounted, the child vue-flickity component won't be mounted yet. Instead I think it should be in the init() method on the actual component, eg.

init() {
      this.$nextTick(() => {
          this.$flickity = new Flickity(this.$el, this.options);
          this.$emit('init', this.$flickity);
    });
},

I'm not actually using this component as I'd already written my own that does exactly the same thing, but that's working for me.

fatihgune commented 6 years ago

Heres a quick workaround for future visitors; for the first render don't load your component until the array is populated and upon updating the array re-render the whole component via a v-if flag that's being toggled in the server call. Additionally wrapping vue's transition component around your component will actually make it behave sort of normal.

davidjmz commented 4 years ago

Im having this problem too, I have my cells with a v-for and they load correctly, but the slider doesn't work until I change pages, the first load is just cells in top of other cells. Im triyng with v-if for the container, but I got the same result. Any ideas?

roberttolton commented 2 years ago

Has anyone got a solution for this?

EDIT: Found this https://github.com/drewjbartlett/vue-flickity/issues/2#issuecomment-352671946

And it works, although using slides.length is fine (if your data is an array), not sure why the comment uses Object.keys.

alnazer commented 1 year ago