wrapping swiper-containers inside ng-container , getting issue with properties initialisation

389 views Asked by At

when I wrap swiper-container inside ng-container some properties that are on swiper-container is not working... why?
without using ng-container all work good

HTML:

full-screen-widget.component.html
<ng-container *ngIf="data?.nodes?.length > 0">
<div class="carousel-component carousel-pagination">
  <div class="title-wrapper ion-text-center mb-30 hide-desktop">
    <h2 class="section-title">Pune's Favorite</h2>
    <p class="section-sub-title">2.1 Full screen banner with caption</p>
  </div>
  <div class="swiper banner-carousel">
    <div class="swiper-wrapper">
      <swiper-container appSwiperContainer [config]="fullscreenSliderWidget">
        <swiper-slide>
          <div class="swiper-slide">
            <img src="../../assets/images/banner.jpg" alt="banner" />
            <div class="banner-content">
              <div class="container">
                <h2 class="title mt-0 mb-0">Squeezo Grill Veg Sandwhe...</h2>
                <p class="sub-title mb-0 mt-20">Subtitle goes here</p>
              </div>
            </div>
          </div>
        </swiper-slide>
        <swiper-slide>
          <div class="swiper-slide">
            <img src="../../assets/images/banner.jpg" alt="banner" />
            <div class="banner-content">
              <div class="container">
                <h2 class="title mt-0 mb-0">Squeezo Grill Veg Sandwhe...</h2>
                <p class="sub-title mb-0 mt-20">Subtitle goes here</p>
              </div>
            </div>
          </div>
        </swiper-slide>
        <swiper-slide>
          <div class="swiper-slide">
            <img src="../../assets/images/banner.jpg" alt="banner" />
            <div class="banner-content">
              <div class="container">
                <h2 class="title mt-0 mb-0">Squeezo Grill Veg Sandwhe...</h2>
                <p class="sub-title mb-0 mt-20">Subtitle goes here</p>
              </div>
            </div>
          </div>
        </swiper-slide>
      </swiper-container>
    </div>
  </div>
</div>
</<ng-container>

TS:

full-screen-widget.component.ts
import { Component, OnInit } from '@angular/core';
import { SwiperOptions } from 'swiper';
import { AuthService } from 'src/app/auth/auth.service';
import { HttpService } from 'src/app/services/http.service';
import { RoutingService } from 'src/app/services/routing.service';

@Component({
  selector: 'app-full-screen-widget',
  templateUrl: './full-screen-widget.component.html',
  styleUrls: ['./full-screen-widget.component.scss']
})
export class FullScreenWidgetComponent implements OnInit {
  public fullscreenSliderWidget: SwiperOptions = {
    loop: true,
    autoplay: {
      delay: 3000
    },
    pagination: {
      el: '.swiper-pagination'
    },

    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev'
    }
  };
  

 constructor(private httpService: HttpService, private routing: RoutingService, private authService: AuthService) {
    let timeElapsed = 0;
    var interval = setInterval(() => {
      if (this.httpService.appCache.cache_id && this.httpService.appCache.cache_id != 'empty') {
        this.data = this.httpService.appCache.data;
        console.log('Nodes List', this.data.nodes);
        console.log('nodes length ', this.data.nodes.length);

        clearInterval(interval);
        if (
          this.httpService.sess?.service_area_screen != 1 &&
          this.httpService.appCache.data.options?.service_area_enabled
        ) {
          this.routing.go('/service-area');
        }
      } else {
        timeElapsed += 10;
        if (timeElapsed >= 10000) {
          console.log('Time limit exceeded of httpService.appCache.cache_id.', timeElapsed);
          clearInterval(interval);
        }
      }
    }, 10);
  }

  ngOnInit() {}
}

Module : for above componet

import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FullScreenWidgetComponent } from './full-screen-widget/full-screen-widget.component';
import { DirectivesModule } from 'src/app/directives/swiper-container.module';
import { ProductSliderWidgetComponent } from './product-slider-widget/product-slider-widget.component';
@NgModule({
  declarations: [FullScreenWidgetComponent, ProductSliderWidgetComponent],
  imports: [CommonModule, DirectivesModule],
  exports: [FullScreenWidgetComponent, ProductSliderWidgetComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class WidgetsModule {}

this is also register at app.componet.ts :

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

register();

directive Used :

import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
import { SwiperOptions } from 'swiper';

@Directive({
  selector: '[appSwiperContainer]'
})
export class SwiperContainerDirective implements AfterViewInit {
  private readonly swiperElement: HTMLElement;
  @Input('config')
  config?: SwiperOptions;

  constructor(private element: ElementRef<HTMLElement>) {
    this.swiperElement = element.nativeElement;
  }

  ngAfterViewInit(): void {
    Object.assign(this.element.nativeElement, this.config);
    //@ts-ignore - We ignore this because there is no initialize method on the HTMLElement
    this.element.nativeElement.initialize();
  }
}

Autoplay is not working when wrap inside ng-container.... how to resolve this?

1

There are 1 answers

2
OZIM TIM On

The problem with autoplay not working when the swiper-container is inside an ng-container might be related to Angular's lifecycle and change detection.

Here's a bit more context: Angular change detection is responsible for keeping the DOM in sync with your data models. ng-container is an Angular directive that acts as a logical container. It doesn't create a DOM element, and the lifecycle hooks on ng-container will not be called when it's rendered in the view.

That's why when you use *ngIf inside ng-container, the ngAfterViewInit() lifecycle hook for the SwiperContainerDirective might not be called. In other words, the swiper container is not fully initialized when ngAfterViewInit() is executed.

You might want to manually trigger the initialization process once your data is ready. Here's an example:

@Directive({
  selector: '[appSwiperContainer]'
})
export class SwiperContainerDirective implements AfterViewInit, OnChanges {
  private readonly swiperElement: HTMLElement;
  
  @Input('config')
  config?: SwiperOptions;

  constructor(private element: ElementRef<HTMLElement>) {
    this.swiperElement = element.nativeElement;
  }

  ngAfterViewInit(): void {
    this.initializeSwiper();
  }

  ngOnChanges(): void {
    this.initializeSwiper();
  }

  private initializeSwiper(): void {
    if (this.config) {
      Object.assign(this.element.nativeElement, this.config);
      //@ts-ignore - We ignore this because there is no initialize method on the HTMLElement
      this.element.nativeElement.initialize();
    }
  }
}

In this case, the swiper gets initialized not only after the view is initialized but also whenever the input data changes, which should ensure that it's initialized once the data is available.