banthagroup / fslightbox-vue

Basic version of Fullscreen Lightbox for Vue.js. Website: https://fslightbox.com/vue
MIT License
41 stars 3 forks source link

can't load source dynamically #32

Closed erkage closed 3 years ago

erkage commented 4 years ago

I'm using the Vue environment. Here is my use case:

<template>
    <div id="products">
        <FsLightbox
            :toggler="toggler"
            :sources="productImages"
            :key="productId"
            :slide="slide"
        />
        <app-product-card 
            v-for="product in products" 
            :key="product.id" 
            :product="product"
            :lightbox="openLightboxOnSlide"
        ></app-product-card>
    </div>
</template>

<script>
export default {
    data() {
        return {
            products: null,
            toggler: false,
            slide: 0,
            productId: null,
            productImages: []
        }
    },
    ...,
    methods: {
        openLightboxOnSlide: function(productId, imageIndex) {
            this.productImages = this.products[productId].images;
            this.slide = imageIndex + 1;
            this.productId = productId; //important line !!!
            this.toggler = !this.toggler;
        }
    }
}
</script>

In the child component (product-card) i'm loading the images with v-for of each product and using event: @click="lightbox(product.id, imageIndex)"

If i click on one of the image first time nothing happens and i've getting [Vue warn]: Duplicate keys detected: '30'. This may cause an update error. in console where "30" is the product's id and referencing to the this.productId = ... line. After clicking on the same image second time get the same error but the FsLightbox loaded with the specific picture.

I've tried everything but nothing worked. Thanks in advance.

piotrzdziarski commented 3 years ago

You are getting: [Vue warn]: Duplicate keys detected: '30'. This may cause an update error. Because you already have one child with this key - app-product-card. So you need to somehow restructure your app to avoid same keys in one component.

When it comes to not opening lightbox - Vue performs updates asynchronously: https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue So all the states changes in openLightboxOnSlide method happens simultaneously. As you update key there you get new lightbox with given props as base values. So the toggler you pass there is new lightbox base value. You don't update it. That's why lightbox is not opening.

The solution is to use Vue nextTick function: https://vuejs.org/v2/api/#Vue-nextTick

openLightboxOnSlide: function(productId, imageIndex) {
  this.productImages = this.products[productId].images;
  this.slide = imageIndex + 1;
  this.productId = productId; //important line !!!
  this.$nextTick(() => {
      this.toggler = !this.toggler;
  });
}