viktorlarsson / vue-tiny-slider

Vanilla javascript slider for all purposes created by ganlanyuan in Vue.
MIT License
135 stars 51 forks source link

Does not work when slider items are generated using v-for directives #7

Closed bharathvaj-ganesan closed 5 years ago

viktorlarsson commented 6 years ago

I'll look into that!

ux-leap commented 6 years ago

Is there any update on this one? This is what I'm doing at the moment and having an issue of using your slider...


<template>
<div>
  <h1>Slider</h1>

  <tiny-slider :mouse-drag="true" :loop="false" items="3" gutter="20" v-for="item in items">
    <div>{{item.name}}</div>
  </tiny-slider>

</div>
</template>

<script>
import VueTinySlider from 'vue-tiny-slider';

export default {
  components: {
    'tiny-slider': VueTinySlider
  },
  name: 'itemscomponent',
  data: function() {
    return {
      items: null
    }
  },
  methods: {
    fetchData: function() {
      let self = this
      const myRequest = new Request('http://0.0.0.0:4000/data/items.json')

      fetch(myRequest)
        .then((response) => {
          return response.json()
        })
        .then((data) => {
          self.items = data
        }).catch(error => {
          console.log(error);
        });
    }
  },

  mounted() {
    this.fetchData()
  }
}
</script>```
viktorlarsson commented 6 years ago

Sorry for the late delay, just had a kid so couldn't find the time.

You need to move the v-for inside the component, . I've created a jsfiddle here: https://jsfiddle.net/mqns0cqq/1/

bharathvaj-ganesan commented 6 years ago

Congrats @viktorlarsson 🎉 Yea it works fine when hardcoded. If the data items were from the server it won't work, because tiny js works as soon as the page loaded modifies the dom, but vuejs renders the component with empty sliders and then updates the sliders with server result. So tiny js doen't doesn't know about the recent addition of items. It thinks "Oh there is no items" even vuejs updates the components

viktorlarsson commented 6 years ago

Thanks!

In your case you have to wait for the data to load prior to rendering the slider. So try putting a v-if on your slider and then you wait for the data to load.

https://jsfiddle.net/mqns0cqq/2/

viktorlarsson commented 6 years ago

Did this solve it @bharathvaj1995 ?

bharathvaj-ganesan commented 6 years ago

No. @viktorlarsson . Tiny silder works by creating wrapping doms. As soon as you initialize the plugin tiny slider creates wrapping dom. When the data is received from the server, Vue updates the dom which has been previously modified by the tiny slider. So tiny slider list won't be updated. Only the doms will be created. Try this case and let me know. Current work around is to initialise the plugin on update life hook of the component. This is what i did. Is there proper solution?

viktorlarsson commented 6 years ago

I'll look into that!

viktorlarsson commented 6 years ago

Sorry for the delay, but we came across a similar issue now. We added a option called "auto-init"

<vue-tiny-slider
        :auto-init="false" 
        ref="slider"
.... </vue-tiny-slider>

This disables the init inside mounted() in the plugin.

Then we manually init the plugin using a computed watcher (in TypeScript). In this case, we have to wait for the images to have been loaded by the browser:

    get imagesAreLoaded(): boolean {
        return this.images.items.length > 0 && this.imagesLoaded === this.images.items.length;
    }

    @Watch('imagesAreLoaded')
    private initSlider() {
        if (this.imagesAreLoaded) {
            const slider= this.$refs.slideras VueTinySlider;
            slider.init();
        }
    }

Is this of any help to you?

viktorlarsson commented 6 years ago

I know it's been a while, but are you able to test this @bharathvaj1995 ?

danstans commented 6 years ago

Hey @viktorlarsson and @bharathvaj1995, I'm having some difficulties getting the slider to work after pulling data from the CMS and stored in Vuex. Let me dump what I have in a gist and if you can help me find a solution I would be very grateful.

https://gist.github.com/danstans/6aa7d17734bfa6c56f9200f4fca3184a Thanks!

marcelogaia commented 6 years ago

After the data is loaded, I can also use: this.$nextTick( () => slider.init() ); Is this a good way to go about it?

viktorlarsson commented 5 years ago

Closing due to inactivity!