Swiper: Loop: true not working when slidesPerView and slidesPerColumn set

Created on 20 Mar 2018  路  9Comments  路  Source: nolimits4web/swiper

It appears others ran into this same issue last year https://github.com/nolimits4web/Swiper/issues/1922 though looks like it was closed. One person mentioned adding:

setTimeout(function(){
    mySwiper.update(true);
    mySwiper.slideTo(0, 0)
}, 100);

to fix the issue. I'm not sure where to add that as I added to here and caused things to break.

var mySwiper = new Swiper ('#my-swiper', {
  slidesPerView: 3,
  slidesPerColumn: 2,
  spaceBetween: 30,
  speed: 2000,
  loop: true,
setTimeout(function(){
    mySwiper.update(true);
    mySwiper.slideTo(0, 0)
}, 100);
  autoplay: {
    delay: 1000,
    disableOnInteraction: false,
  },

Is there somewhere else it should be added or is there another fix, so that loop true works out of the box when using slides per view and slides per column? Thanks for any help anyone may have!

stale

Most helpful comment

slidesPerColumn doesn't compatible with loop

& slidesPerColumn can't be changed within breakpoints

Ironic for a product maintained by someone with a name like 'nolimits4web'.

All 9 comments

slidesPerColumn doesn't compatible with loop

Hi yes, that's the issue I'm experiencing. Hopefully it can eventually be fixed. In the meantime, a workaround appears to be creating two instances of swiper one for the top row and one for the bottom and then removing slides per column. Not ideal, but works.

loop: true also not work with slidesPerView: 'auto' event have specified loopedSlides, below link for reference:
https://stackblitz.com/edit/angular-gnd8mj

+1, experiencing similar problems when using loopedSlides and slidesPerView: 'auto'.
The setTimeout solution didn't work for me either (and is kind of dirty).

Looks like this issue was present at least as far back as v3.4.0, maybe earlier.
http://idangero.us/swiper/forum/#!/bugs-and-issues:need-two-clicks-to-activate

Here is an version of the jsfiddle from the link above, updated for v4.2.6. Swiper config (minimal) is at the bottom of the JS window.
https://jsfiddle.net/n88Lhesr/4/
To reproduce, click the right arrow button 3 times to get to slide 3, then click the left button.
Expected: It goes back to slide 2
Actual: Slide 2 vanishes and it stays on slide 3 (I think it's jumping to the duplicated slide 3 that exists to the far left of the "real" slides, which is the true slide index 0).

EDIT: Messed around with it a bit more, and found a possible solution: in the swiper.js code, change the first part of the "Fix For Positive Oversliding" conditional from:

    } else if ((params.slidesPerView === 'auto' && activeIndex >= loopedSlides * 2) || (activeIndex > slides.length - (params.slidesPerView * 2))) {
      // Fix For Positive Oversliding

to:

    } else if ((activeIndex >= (slides.length - 1) - (loopedSlides))) {
      // Fix For Positive Oversliding

This works for my case, but it's a bit heavy-handed -- might not be sufficient for all cases where slidesPerView is set to 'auto'. For example, if slide widths are narrow and loopedSlides is low, then the loopfix needs to happen before the active index reaches the last "real" slide, otherwise I imagine there'd be some empty space showing up at the end of the slides. But then I guess you could just increase loopedSlides in that case.

Official fix would be appreciated!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been automatically closed due to inactivity. If this issue is still actual, please, create the new one.

slidesPerColumn doesn't compatible with loop

& slidesPerColumn can't be changed within breakpoints

Ironic for a product maintained by someone with a name like 'nolimits4web'.

This happens when you're using the tag. I fixed it by using "directive" mode

<div  class="swiper-container carousel" [swiper]="slideConfig" (init)="swiperInit($event)" (reachEnd)="swiperReachEnd($event)" (reachBeginning)="swiperReachBeginning($event)" (slideChange)="swiperSlideChange($event)">
 <div class="swiper-wrapper">

I highly recommend doing it using the above method (you have to import the css class as well)

I RECOMMEND AGAINST THE FOLLOWING. It's more for if you for some reason can't use the approach above.

However, if you have to use then I was able to _HACK_ it with something like the following (won't work for more than 1 carousel and you can't pass $event in this mode to the handlers to differentiate carousels, so you'd have to pass the id in and that'd get ugly).

swiperInit(e) {
    // Note: e will not have anything useful when using <swiper>. For angular $event to work right, you have to use <div>, not <swiper>
    var mySwiper = document.querySelector('.swiper-container').swiper; // If you have multiple carousels, you'll need to somehow find the right one

    var origFinalSlideIdx = mySwiper.slides.length - 1;
    var prependArray = [];
    var appendArray = [];
    for (var i = 0; i < mySwiper.params.slidesPerView; i++)
    {
        appendArray[i] = mySwiper.slides[i].innerHTML;
        prependArray[i] = mySwiper.slides[origFinalSlideIdx - i].innerHTML
    }
    // Prepend and append
    for (var i = 0; i < mySwiper.params.slidesPerView; i++)
    {
        mySwiper.appendSlide(appendArray[i]);           
        mySwiper.prependSlide(prependArray[i]);
    }
    mySwiper.update();
    mySwiper.autoplay.start();
    mySwiper["loopToReverse"] = origFinalSlideIdx + 1; // Put it on the element, in case we have multiple per page
}

swiperReachEnd(e) { 
}

swiperReachBeginning(e) {       
    // Note: e will not have anything useful when using <swiper>. For angular $event to work right, you have to use <div>, not <swiper>
    console.log("swiperReachBeginning");
    var mySwiper = document.querySelector('.swiper-container').swiper; // If you have multiple carousels, you'll need to somehow find the right one
    mySwiper.slideTo(mySwiper["loopToReverse"], 0, true);
}

swiperSlideChange(e) {
    // Note: e will not have anything useful when using <swiper>. For angular $event to work right, you have to use <div>, not <swiper>
    var mySwiper = document.querySelector('.swiper-container').swiper; // If you have multiple carousels, you'll need to somehow find the right one
    console.log("swiperSlideChange " + mySwiper.activeIndex + " " + mySwiper.realIndex + " " + mySwiper.previousIndex);
    console.log("autoplay.running: " + mySwiper.autoplay.running)

    if (mySwiper.activeIndex > mySwiper.slides.length - mySwiper.params.slidesPerView - 1)  
    {   
        mySwiper.slideTo(mySwiper.params.slidesPerView, 1, false); // Has to be 1, because autoplay waits for transition
    }
}

Number of slides per column, for multirow layout
slidesPerColumn > 1 is currently not compatible with loop mode (loop: true)
馃槩

Was this page helpful?
0 / 5 - 0 ratings