vitalii-andriiovskyi / ngx-owl-carousel-o

owl-carousel for Angular >=6
MIT License
177 stars 51 forks source link

Carousel does not get resized until page reload #266

Closed Dragosp33 closed 10 months ago

Dragosp33 commented 10 months ago

I am using angular 14 with "ngx-owl-carousel-o": "^14.0.1". ( latest ). It seems that the responsiveness of the carousel breaks if the window gets resized, but comes back online if the page is reloaded. For example:

On the initial loading: initial_carousel

then after resize: on_resize_no_refresh_carousel

and then, if reloaded, it gets the correct width: after_refresh_carousel

I looked into more solutions and none seems to work. I looked into #107 but this doesn't seem to be my problem, as I put this directly on body.

This is my template.html:

<owl-carousel-o [options]="customOptions">
  <ng-container *ngFor="let slide of bikes_type">
    <ng-template carouselSlide [id]="slide.id">
      <div class="pb-5">
        <div
          class="product-item position-relative bg-light d-flex flex-column text-center"
        >
          <img
            class="img-fluid mb-4"
            [src]="slide.image_url"
            [alt]=""
            [title]="slide.nume"
          />
          <!--<div class="myitem" [style.background-image]= "'url(' + slide.image_url + ')'"></div>-->
          <h6 class="text-uppercase">{{ slide.nume }}</h6>
          <div class="btn-action d-flex justify-content-center">
            <a class="btn btn-primary py-2 px-3" href=""
              ><i class="bi bi-cart"></i
            ></a>
            <a class="btn btn-primary py-2 px-3" href=""
              ><i class="bi bi-eye"></i
            ></a>
          </div>
        </div>
      </div>
    </ng-template>
  </ng-container>
</owl-carousel-o>

and this is my template.ts:

import { bikes_typeService } from '../../services/bikes_type.service';
import { Component, HostListener, OnInit } from '@angular/core';
import { OwlOptions } from 'ngx-owl-carousel-o';
import { Bikes_type } from 'src/app/interfaces/bikes_type';

import { HttpErrorResponse } from '@angular/common/http';

@Component({
  selector: 'app-products',
  templateUrl: './test-template.html',
  styleUrls: ['./products.component.css'],
})
export class ProductsComponent implements OnInit {
  public bikes_type: Bikes_type[];
  customOptions: OwlOptions = {
    autoplay: true,
    smartSpeed: 1000,
    margin: 45,
    navSpeed: 600,
    dots: false,
    loop: true,
    // responsiveBaseElement: 'true',

    navText: [
      '<i class="bi bi-arrow-left"></i>',
      '<i class="bi bi-arrow-right"></i>',
    ],
    responsive: {
      0: {
        items: 1,
      },
      768: {
        items: 2,
      },
      992: {
        items: 3,
      },
      1200: {
        items: 3,
      },
    },

    nav: true,
    responsiveRefreshRate: 500,
  };

  constructor(private bikes_typeService: bikes_typeService) {
    this.bikes_type = [];
  }

  ngOnInit() {
    this.getBikes();

    setTimeout(() => {
      this.customOptions = {
        autoplay: true,
        smartSpeed: 1000,
        margin: 45,
        navSpeed: 600,
        dots: false,
        loop: true,
        // responsiveBaseElement: 'true',

        navText: [
          '<i class="bi bi-arrow-left"></i>',
          '<i class="bi bi-arrow-right"></i>',
        ],
        responsive: {
          0: {
            items: 1,
          },
          768: {
            items: 2,
          },
          992: {
            items: 3,
          },
          1200: {
            items: 3,
          },
        },

        nav: true,
        responsiveRefreshRate: 200,
      };
    }, 200);
  }

  public getBikes(): void {
    this.bikes_typeService.getBikesType().subscribe(
      (Response: Bikes_type[]) => {
        this.bikes_type = Response;
      },
      (error: HttpErrorResponse) => {
        console.log(error);
        alert(error.message);
      }
    );
  }

I tried with these solutions I found online but nothing seems to work:

 updateCarousel(): void {
    // Use a timeout to allow time for the DOM to update after a resize
    setTimeout(() => {
      this.customOptions = { ...this.customOptions };
      // console.log(this.customOptions);
    }, 20);
  }

  @HostListener('window:resize', ['$event'])
  onResize(event: any): void {
    this.updateCarousel();
Dragosp33 commented 10 months ago

Also, with this configuration for the component.ts :

export class ProductsComponent implements OnInit {
  public bikes_type: Bikes_type[];
  customOptions: OwlOptions = {
    autoplay: true,
    smartSpeed: 1000,
    margin: 45,
    navSpeed: 600,
    dots: false,
    loop: true,

    navText: [
      '<i class="bi bi-arrow-left"></i>',
      '<i class="bi bi-arrow-right"></i>',
    ],
    responsive: {
      0: {
        items: 1,
      },
      768: {
        items: 2,
      },
      992: {
        items: 3,
      },
      1200: {
        items: 3,
      },
    },

    nav: true,
    responsiveRefreshRate: 500,
  };

  constructor(private bikes_typeService: bikes_typeService) {
    this.bikes_type = [];
  }

  ngOnInit() {
    this.getBikes();

    setTimeout(() => {
      this.customOptions = {
        autoplay: true,
        smartSpeed: 1000,
        margin: 45,
        navSpeed: 600,
        dots: false,
        loop: true,

        navText: [
          '<i class="bi bi-arrow-left"></i>',
          '<i class="bi bi-arrow-right"></i>',
        ],
        responsive: {
          0: {
            items: 1,
          },
          768: {
            items: 2,
          },
          992: {
            items: 2,
          },
          1200: {
            items: 2,
          },
        },

        nav: true,
        responsiveRefreshRate: 200,
      };
    }, 200);
  }

  public getBikes(): void {
    this.bikes_typeService.getBikesType().subscribe(
      (Response: Bikes_type[]) => {
        this.bikes_type = Response;
      },
      (error: HttpErrorResponse) => {
        console.log(error);
        alert(error.message);
      }
    );
  }

  updateCarousel(): void {
    // Use a timeout to allow time for the DOM to update after a resize
    setTimeout(() => {
      this.customOptions = { ...this.customOptions, autoWidth: true };
      // console.log(this.customOptions);
    }, 20);
  }

  @HostListener('window:resize', ['$event'])
  onResize(event: any): void {
    this.updateCarousel();
  }
}

I get this errors logs: -> I have two slides, so in my options I have 1 slide for small (0) to medium (768) and two for rest of breakpoints in the responsive option. As you can see in this logs, it seems that even though the window is resized from initial large breakpoint that showed two slides, it still wants to show two slides on the small breakpoints. no-responsive-carousel-options

Dragosp33 commented 10 months ago

Solved this. After a bit of digging it seems that for my slides ( they are gotten from a backend api ), even though their interface uses String for the ids, it somehow was transformed to a Number. A simple slide.id.toString() in the <ng-template carouselSlide [id]="slide.id.toString()" style="width: 100%"> made it work.