htmlangularangularjstypescriptswiper.js

SlideChange(Swiper) event is not functional


I have the following situation: I'm trying to use the Swiper library to change pictures as a carousel.

I'm using Angular 16(I will soon upgrade to v18) and the latest version of Swiper, when selecting to the next picture in the list I don't get the slidechange event.

I wanted to change data in the table after changing the image in the carousel, so I needed this event.

Template:
<swiper-container [slidesPerView]="1" [centeredSlides]="true" [navigation]="true" [pagination]="{ clickable: true }" (slidechange)="onSlideChange($event)">
    <swiper-slide *ngIf="topIssue.DescriptionPhoto.Base64StringData.length> 0"> 
    <img [src]="topIssue.DescriptionPhoto.Base64StringData" /></swiper-slide>
    <swiper-slide *ngIf="topIssue.FurtherActionPhoto.Base64StringData.length> 0"> 
    <img [src]="topIssue.FurtherActionPhoto.Base64StringData" /></swiper-slide>
</swiper-container>

Component:
  onSlideChange(swiper: any) {
    console.log(swiper);
  }

AppModule:
import { register } from 'swiper/element/bundle';


export class AppModule {
  constructor() {
    registerLocaleData(localeDe);
    register();
  }
}

Solution

  • If you want to perform the listener action from TS, we can use addEventListener, with the name as swiperslidechange, I am using AbortController to remove the listener.

    export class App {
      abort: AbortController = new AbortController();
      ...
    
      ...
    
      ngAfterViewInit() {
        this.swiper.nativeElement.addEventListener(
          'swiperslidechange',
          (event: any) => {
            const [swiper, progress] = event.detail;
            console.log('from TS:', event);
          }, {
            signal: this.abort.signal,
          }
        );
      }
      ...
    
      ...
      ngOnDestroy() {
        this.abort.abort();
      }
    }
    

    If you want to listen to DOM events, you can listen for swiperslidechange HTML event with angular event binding.

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

    TS:

    swiperslidechange(data: any) {
      console.log('from DOM', data);
    }
    

    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 (swiperslidechange)="swiperslidechange($event)">
          @for (projectImagePath of projectImagesPath; track projectImagePath) {
            <swiper-slide>
              <img [src]="projectImagePath" alt=""/>
            </swiper-slide>
          }
        </swiper-container>
      `,
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    })
    export class App {
      abort: AbortController = new AbortController();
      @ViewChild('swiper') swiper!: ElementRef<any>;
      projectImagesPath = [
        'https://placehold.co/600x400?1',
        'https://placehold.co/600x400?2',
        'https://placehold.co/600x400?3',
        'https://placehold.co/600x400?4',
      ];
    
      swiperslidechange(data: any) {
        console.log('from DOM', data);
      }
    
      ngAfterViewInit() {
        // swiper parameters
        const swiperParams = {
          slidesPerView: 1,
          navigation: true,
          loop: true,
          pagination: { clickable: true },
        };
        Object.assign(this.swiper.nativeElement, swiperParams);
        this.swiper.nativeElement.initialize();
    
        this.swiper.nativeElement.addEventListener(
          'swiperslidechange',
          (event: any) => {
            const [swiper, progress] = event.detail;
            console.log('from TS:', event);
          },
          {
            signal: this.abort.signal,
          }
        );
      }
    
      ngOnDestroy() {
        this.abort.abort();
      }
    }
    

    Stackblitz Demo