typescriptionic-frameworkswiper.jsionic5ion-slides

Multiple ion-slides in loop not providing correct index on slides


In my Ionic 5 app I have to display my custom component horizontally by ion-slides and repet each slider vertically in loop.

Following in the code.

<ng-container *ngFor="let item of mainList; let i = index;">
  <ion-slides pager="true" loop="true" [options]="slideOpts" (ionSlideDidChange)="slideChanged(i)" #slides>
      <ion-slide *ngFor="let id of item.subList; let j = index;">
        <app-cust-comp [input]="j"></app-cust-comp>
      </ion-slide>
  </ion-slides>
</ng-container>

Following method for getting the active slide number

      @ViewChild('slides') slides: IonSlides;

      async slideChanged(i: number){
        const activeSlideNumber = await this.slides.getActiveIndex();
        console.log(i+' '+slideNumber);
      }

My goal is get the correct active slide number for each index. The sliders are working perfectly and the value of activeSlideNumber is correct every time for only the first (index 0) slider. For all sliders except first one the value of activeSlideNumber is always the last value change by first (index 0) slider. So if I slide the first (index 0) slider 3 times and the activeSlideNumber for index 0 is 2. It will always come as 2 for all other slider.


Solution

  • The issue is that you have multiple instances of an ion-slider in your view but ViewChild is used to get only one instance of the slider.

    You should use ViewChildren instead:

    @ViewChildren(IonSlides) slides: QueryList<IonSlides>;

    Please take a look at this Stackblitz demo.

    Demo gif

    Component:

    import { Component, QueryList, ViewChildren } from '@angular/core';
    import { IonSlides } from '@ionic/angular';
    
    @Component({
      selector: 'app-home',
      templateUrl: 'home.page.html',
      styleUrls: ['home.page.scss']
    })
    export class HomePage {
    
      @ViewChildren(IonSlides) slides: QueryList<IonSlides>; // <-- here!
    
      // Some fake data...
      public items = [
        {
          itemId: '1',
          subOptions: ['Option 1', 'Option 2', 'Option 3']
        },
        {
          itemId: '2',
          subOptions: ['Option 4', 'Option 5', 'Option 6']
        },
        {
          itemId: '3',
          subOptions: ['Option 7', 'Option 8', 'Option 9']
        }
      ]
    
      constructor() {}
    
      public async slideChanged(i: number){
        console.log(`Slider ${i} changed`);
    
        // Iterate over the list of sliders to get all the selected indexes
        this.slides.toArray().forEach(async (slider, index) => {
          console.log(`Slider ${index} selected index: ${await slider.getActiveIndex()}`);
        })
      }
    
    }
    

    View:

    <ion-header>
      <ion-toolbar>
        <ion-title>
          Home
        </ion-title>
      </ion-toolbar>
    </ion-header>
    
    <ion-content class="ion-padding">
      <ng-container *ngFor="let item of items; let i = index">
        <ion-slides pager="true" loop="true" (ionSlideDidChange)="slideChanged(i)">
            <ion-slide *ngFor="let id of item.subOptions; let j = index;">
              <p>(i: {{ i }} j: {{  j}}) {{ id }}</p>
            </ion-slide>
        </ion-slides>
      </ng-container>
    </ion-content>