1

In my angular application, I have 4 swiper slide, which i want to render conditionally. But its not working properly. I have added images as well at bottom.

Issue - On initial load all swiper are rendering properly with 4 slides per view. But suppose if select swiper_1 then its showing 1 slide per view but according to swiperParam it should show 4 slide per view. If I select others like swiper_2, or swiper_3, then its showing 4 slides per view, and then if i select all then all swiper are showing 4 slide per view except the previous selected swiper "swiper_2 or swiper_3".

I think the parameters are not getting applied properly.

Typescript ->

import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, NgZone, QueryList, Renderer2, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-swiper-testing',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './swiper-testing.component.html',
  styleUrls: ['./swiper-testing.component.scss'],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  encapsulation: ViewEncapsulation.None,
})
export class SwiperTestingComponent {

  constructor(private el: ElementRef, private cdRef: ChangeDetectorRef, private ngZone: NgZone, private renderer: Renderer2) { }

  @ViewChild('swiper_1') swiper_1!: ElementRef;
  @ViewChild('swiper_2') swiper_2!: ElementRef;
  @ViewChild('swiper_3') swiper_3!: ElementRef;
  @ViewChild('swiper_4') swiper_4!: ElementRef;

  selectedCategories: string = 'all';

  swiperParams = {
    loop: false,
    slidesPerView: 1,
    spaceBetween: 24,
    breakpoints: {
      640: {
        slidesPerView: 2,
      },
      1024: {
        slidesPerView: 3,
      },
      1200: {
        slidesPerView: 4,
      },
      1500: {
        slidesPerView: 4.5,
      },
      1700: {
        slidesPerView: 5,
      },
      1900: {
        slidesPerView: 5.5,
      },
    },
    navigation: true,
  };
  
  
  ngAfterViewInit() {
    this.swiper_1Swiper();
    this.swiper_2Swiper();
    this.swiper_3Swiper();
    this.swiper_4Swiper();
  }

  categoriesSelect(value: string) {
    if (this.selectedCategories === value) return;
  
    this.selectedCategories = value;
    this.cdRef.detectChanges();
  
    // Let Angular fully update the view first
    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        this.ngZone.run(() => {
          if (value === 'all' || value === 'swiper_1') this.swiper_1Swiper();
          if (value === 'all' || value === 'swiper_2') this.swiper_2Swiper();
          if (value === 'all' || value === 'swiper_3') this.swiper_3Swiper();
          if (value === 'all' || value === 'swiper_4') this.swiper_4Swiper();
        });
      }, 0);
    });
  }
  
  swiper_1Swiper() {
    if (this.swiper_1?.nativeElement) {
      const swiperEl = this.swiper_1.nativeElement;
      Object.assign(swiperEl, this.swiperParams );
      swiperEl.initialize();
    }
  }
  
  
  swiper_2Swiper() {
    if (this.swiper_2?.nativeElement) {
      const swiperEl = this.swiper_2.nativeElement;
      Object.assign(swiperEl, this.swiperParams);
      swiperEl.initialize();
    }
  }
  swiper_3Swiper() {
    if (this.swiper_3?.nativeElement) {
      const swiperEl = this.swiper_3.nativeElement;
      Object.assign(swiperEl, this.swiperParams);
      swiperEl.initialize();
    }
  }
  swiper_4Swiper() {
    if (this.swiper_4?.nativeElement) {
      const swiperEl = this.swiper_4.nativeElement;
      Object.assign(swiperEl, this.swiperParams);
      swiperEl.initialize();
    }
  }
  

}

HTML ->

<div>
    <div class="main">
        <div class="filter-container d-flex justify-content-between align-items-start">
            <button type="button" class="btn btn-primary selected" (click)="categoriesSelect('all')">All
                swiper</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_1')">swiper 1</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_2')">swiper 2</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_3')">swiper 3</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_4')">swiper 4</button>
        </div>
        <div class="d-flex flex-column gap-4 mt-48">

            <div class="cards-swiper-container"
                *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_1'">
                <h4 class="mb-0">swiper_1 </h4>
                <div class="navigation-wrapper"></div>
                <swiper-container class="mySwiper" init="false" #swiper_1>
                    <swiper-slide *ngFor="let item of [1,2,3,4,5,6,7,8];">
                    </swiper-slide>
                </swiper-container>
            </div>
            <div class="cards-swiper-container" *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_2'">
                <h4 class="mb-0">swiper_2 </h4>
                <div class="navigation-wrapper"></div>
                <swiper-container class="mySwiper" init="false" #swiper_2>
                    <swiper-slide *ngFor="let item of [1,2,3,4,5,6,7,8];">
                    </swiper-slide>
                </swiper-container>
            </div>
            <div class="cards-swiper-container"
                *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_3'">
                <h4 class="mb-0">swiper_3 </h4>
                <div class="navigation-wrapper"></div>
                <swiper-container class="mySwiper" init="false" #swiper_3>
                    <swiper-slide *ngFor="let item of [1,2,3,4,5,6,7,8];">
                    </swiper-slide>
                </swiper-container>
            </div>
            <div class="cards-swiper-container" *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_4'">
                <h4 class="mb-0">swiper_4 </h4>
                <div class="navigation-wrapper"></div>
                <swiper-container class="mySwiper" init="false" #swiper_4>
                    <swiper-slide *ngFor="let item of [1,2,3,4,5,6,7,8];">
                    </swiper-slide>
                </swiper-container>
            </div>
        </div>
    </div>
</div>

All selected ->

enter image description here

Selected Swiper_1 ->

enter image description here

Selected Swiper_2 ->

enter image description here

Selected All again ->

enter image description here

0

1 Answer 1

1

To create more readable code, create a swiper component which encapsulates the swiper code.

The advantage of this, is when the component is created/destroyed. You will have a fresh initialization of each element.

@Component({
  selector: 'app-swiper-element',
  standalone: true,
  imports: [],
  template: `
    <swiper-container class="mySwiper" init="false" #swiper>
      <swiper-slide *ngFor="let item of items;">
      </swiper-slide>
    </swiper-container>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  encapsulation: ViewEncapsulation.None,
})
export class SwiperElementComponent {
  @Input() items = [1,2,3,4,5,6,7,8];
  @ViewChild('swiper') swiper!: ElementRef;
  @Input() swiperParams: any = null;

  ngAfterViewInit() {
    this.initialize();
  }

  // make swiper react dynamically to @Input changes
  // ngOnChanges() {
  //   this.initialize();
  // }

  initialize() {
    if (this.swiper?.nativeElement &&  this.swiperParams) {
      const swiperEl = this.swiper.nativeElement;
      Object.assign(swiperEl, this.swiperParams );
      swiperEl.initialize();
      // this.cdRef.detectChanges(); // <- add this if needed.
    }
  }
}

Now all we need to do is to add SwiperElementComponent to the imports array of the parent component and simplify the code as below.

@Component({
  selector: 'app-swiper-testing',
  standalone: true,
  imports: [CommonModule, SwiperElementComponent], // <- add here!
  templateUrl: './swiper-testing.component.html',
  styleUrls: ['./swiper-testing.component.scss'],
  encapsulation: ViewEncapsulation.None,
})
export class SwiperTestingComponent {

  constructor(private el: ElementRef, private cdRef: ChangeDetectorRef, private ngZone: NgZone, private renderer: Renderer2) { }

  selectedCategories: string = 'all';

  swiperParams = {
    loop: false,
    slidesPerView: 1,
    spaceBetween: 24,
    breakpoints: {
      640: {
        slidesPerView: 2,
      },
      1024: {
        slidesPerView: 3,
      },
      1200: {
        slidesPerView: 4,
      },
      1500: {
        slidesPerView: 4.5,
      },
      1700: {
        slidesPerView: 5,
      },
      1900: {
        slidesPerView: 5.5,
      },
    },
    navigation: true,
  };

  categoriesSelect(value: string) {
    if (this.selectedCategories === value) return;
  
    this.selectedCategories = value;
    this.cdRef.detectChanges();
  }
}

In the HTML, just pass in the params to this component.

<div>
    <div class="main">
        <div class="filter-container d-flex justify-content-between align-items-start">
            <button type="button" class="btn btn-primary selected" (click)="categoriesSelect('all')">All
                swiper</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_1')">swiper 1</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_2')">swiper 2</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_3')">swiper 3</button>
            <button type="button" class="btn btn-primary" (click)="categoriesSelect('swiper_4')">swiper 4</button>
        </div>
        <div class="d-flex flex-column gap-4 mt-48">

            <div class="cards-swiper-container"
                *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_1'">
                <h4 class="mb-0">swiper_1 </h4>
                <div class="navigation-wrapper"></div>
                <app-swiper-element [swiperParams]="swiperParams">
                </app-swiper-element>
            </div>
            <div class="cards-swiper-container" *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_2'">
                <h4 class="mb-0">swiper_2 </h4>
                <app-swiper-element [swiperParams]="swiperParams">
                </app-swiper-element>
            </div>
            <div class="cards-swiper-container"
                *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_3'">
                <h4 class="mb-0">swiper_3 </h4>
                <div class="navigation-wrapper"></div>
                <app-swiper-element [swiperParams]="swiperParams">
                </app-swiper-element>
            </div>
            <div class="cards-swiper-container" *ngIf="selectedCategories === 'all' || selectedCategories === 'swiper_4'">
                <h4 class="mb-0">swiper_4 </h4>
                <div class="navigation-wrapper"></div>
                <app-swiper-element [swiperParams]="swiperParams">
                </app-swiper-element>
            </div>
        </div>
    </div>
</div>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.