Owl Carousel + Vue.js with dynamic item

Asked

Viewed 1,038 times

0

Hello, I have a component that initializes a slider with dynamic items coming from the database. However, I have a search box that makes a new request to the database and returns new items to replace the existing ones in the slider. But it’s not replacing, being on top of the slider.

Follow the code of the component template: (There is always a default item (banner_default) that should always be the first slide of the slider)

<template>
<div @click.prevent="refresh()" class="week-slider valign-wrapper"><i class="fa fa-home" aria-hidden="true"></i></div>
<div id="feupworld_slide" class="owl-carousel owl-theme">
    <div class="item">
        <div class="textoverlay firstSlide"><span>{{ week }} / {{ year }}</span></div>
        <img :src="'storage/guest/' + banner_default" alt="#FEUPWORLD">
    </div>
    <div class="item" v-for="slide in slider">
        <div class="textoverlay captionSlide flow-text">
            <a :href="slide.link" target="_blank">
            <span class="background-slide-text show-link" style="font-size: 2.0vw;">{{ slide.title }}</span>
            </a>
            <div style="" class="hashtag">
                <span class="light grey-text text-lighten-3 tags-slide background-slide-text">
                    <span v-for="tag in slide.tags" class="tags" style="font-size: 1.1vw;">#{{ tag.tag }} </span>
                </span>
            </div>
        </div>
        <img :src="'storage/noticias/images/' + slide.photo " alt="#FEUPWORLD">
    </div>
</div>

Follows the script:

<script type="text/javascript">

export default{
    data(){
        return{
            slider: [],
            week: 0,
            init: false,
            banner_default: "banner_default.jpg",
            year: new Date().getFullYear(),
            link: "",
        }
    },
    created(){
        this.imageSlider();
    },
    methods:{
        refresh(){
            location.reload();
        },
        imageSlider(){
            Vue.http.get('imageSlider').then((response) => {
                this.slider = response.data.data;
                this.week = response.data.data[0].week;
            });
            window.Vue.http.interceptors.unshift((request, next) => {
                next(()=> {
                    this.sliderInit();
                });
            });
        },
        sliderInit(){
            if(!this.init){
                this.init = true;
                Vue.nextTick(function () {
                    $("#feupworld_slide").owlCarousel({
                        singleItem:false,
                        items: 1,
                        autoplay: true,
                        autoPlaySpeed: 3000,
                        autoPlayTimeout: 3000,
                        dots: true,
                        loop:true,
                        pagination: true,
                    });
                }.bind(this));
            }
        },
        showWeekYearSlider(){
            this.slider = [];
            Vue.http.get('getimageSliderWeekYear/'+this.year+'/'+this.week).then((response) => {
                this.slider = response.data.data;
            });
        }
    },
    events: {
        'selectBanner'(data){
            this.week = data.week;
            this.year = data.year;
            this.showWeekYearSlider();
        },
    },
}

The "selectBanner" event calls the function that should subscribe to the old slides by the new ones, follows a print of what is doing to me (Superimposes the new images on top of the slider below each other):

inserir a descrição da imagem aqui

The following image on "1" the new slides over the old slide and on "2" shows the Bullets with the amount of previous items but that are now blank keeping only the default slider, which is correct.

inserir a descrição da imagem aqui

1 answer

1

I went through this problem a little while ago, in my case I needed to encapsulate the Owl-Carousel inside a Component.

Owl-Carousel.Vue

<template>
  <ul>
    <slot></slot>
  </ul>
</template>

<script src="./owl-carousel.vue.js"></script>
<style src="./owl-carousel.vue.css"></style>

Owl-Carousel.vue.js

import './assets/owl.carousel.css'
import './assets/owl.theme.css'
import './assets/owl.carousel.js'

export default {
  name: 'OwlCarousel',
  props: {
    items: Number,
    itemsDesktopSmall: Array,
    itemsTablet: Array,
    itemsTabletSmall: Array,
    itemsMobile: Array,
    value: Array
  },
  data () {
    return {
      widget: null
    }
  },
  computed: {
    options () {
      return {
        items: this.items,
        itemsDesktopSmall: this.itemsDesktopSmall,
        itemsTablet: this.itemsTablet,
        itemsTabletSmall: this.itemsTabletSmall,
        itemsMobile: this.itemsMobile,
        navigation: false,
        slideSpeed: 300,
        pagination: true,
        paginationSpeed: 400,
        singleItem: (this.items || 1) === 1,
        navigationText: ['<span class="fa fa-angle-left"></span>', '<span class="fa fa-angle-right"></span>'],
        autoPlay: false
      }
    }
  },
  watch: {
    value: {
      immediate: true,
      handler: function () {
        if (this.widget) {
          this.widget.trigger('destroy.owl.carousel')
          this.widget = null;
        }
        if (this.value && this.value.length > 0) {
          this.$nextTick(() => {
            this.widget = $(this.$el).owlCarousel(this.options)
          })
        }
      }
    }
  }
}

here is an example of using the component.:

<owl-carousel :items="3" :items-desktop-small="[1280,3]" :items-tablet="[900,2]" :items-tablet-small="[750,2]" :items-mobile="[600,1]" v-model="items">
    <li v-for="item in items" :key="item._id">
        ...
    </li>
</owl-carousel>

If Carousel has no dynamic items (which was not our case), it is interesting to add the directive v-once to him. The reason for this is well explained in the following article.: How To (Safely) Use A jQuery Plugin With Vue.js

<owl-carousel :items="3" :items-desktop-small="[1280,3]" :items-tablet="[900,2]" :items-tablet-small="[750,2]" :items-mobile="[600,1]" v-model="items" v-once>
    <li v-for="item in items" :key="item._id">
        ...
    </li>
</owl-carousel>

In my case I was using a third party template, and the theme of it was well customized, so the owl-carousel became a somewhat coupled dependency.

but in general, the use of components based on jQuery, after all the Vue is quite possessive as to DOM and the jQuery is a terrorist who does not respect this.

At this point the Vue Awesome is your friend.: Carousel

Browser other questions tagged

You are not signed in. Login or sign up in order to post.