javascriptangularswiper.js

Loop mode warning: The number of slides is not enough for loop mode


I am using Swiper.js in an Angular project to create a slider. I want the slider to loop, but I am encountering the following warning:

Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled and not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters.

My slidesPerView and slidesPerGroup parameters are set to 1, and I have a total of 4 slides. Even when I duplicate the slides (doubling the number of images), this warning persists, and the loop mode does not work.

Here is my component template:

<swiper-container
  class="slider-container"
  loop="true"
  navigation="true"
  slides-per-view="1"
  slides-per-group="1"
  [pagination]="{ clickable: true }">
  @for (projectImagePath of projectImagesPath; track projectImagePath) {
    <swiper-slide class="slider">
      <img [src]="projectImagePath" alt="">
    </swiper-slide>
  }
</swiper-container>

What I have tried:

Despite these efforts, the loop functionality is not working, and the warning still appears.

Questions:

  1. Why is the loop mode not working even though I have enough slides and meet the documented requirements?
  2. Is there something specific about using Swiper in Angular that could cause this issue?

Here is a Stackblitz Demo


Solution

  • Looks like a bug in swiper when we initialize via HTML, to achieve the functionality, we can initialize through swiper initialize function instead.

    export class App {
      @ViewChild('swiper') swiper!: ElementRef<any>;
    
        ngAfterViewInit() {
          // swiper parameters
          const swiperParams = {
            slidesPerView: 1,
            navigation: true,
            loop: true,
            pagination: { clickable: true },
          };
          Object.assign(this.swiper.nativeElement, swiperParams);
          this.swiper.nativeElement.initialize();
        }
    

    In the HTML, make sure you set the attribute init="false" to prevent auto initialization.

    <swiper-container init="false" #swiper>
      @for (projectImagePath of projectImagesPath; track projectImagePath) {
        <swiper-slide>
          <img [src]="projectImagePath" alt=""/>
        </swiper-slide>
      }
    </swiper-container>
    

    Full Code:

    import {
      Component,
      CUSTOM_ELEMENTS_SCHEMA,
      ElementRef,
      ViewChild,
    } from '@angular/core';
    import { MatGridListModule } from '@angular/material/grid-list';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [MatGridListModule],
      template: `
        <swiper-container init="false" #swiper>
          @for (projectImagePath of projectImagesPath; track projectImagePath) {
            <swiper-slide>
              <img [src]="projectImagePath" alt=""/>
            </swiper-slide>
          }
        </swiper-container>
      `,
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    })
    export class App {
      @ViewChild('swiper') swiper!: ElementRef<any>;
      projectImagesPath = [
        'https://placehold.co/600x400',
        'https://placehold.co/600x400',
        'https://placehold.co/600x400',
        'https://placehold.co/600x400',
      ];
    
        ngAfterViewInit() {
          // swiper parameters
          const swiperParams = {
            slidesPerView: 1,
            navigation: true,
            loop: true,
            pagination: { clickable: true },
          };
          Object.assign(this.swiper.nativeElement, swiperParams);
          this.swiper.nativeElement.initialize();
        }
    }
    

    Stackblitz Demo