angularcarouselslideshow

Carousel in Angular Issue


I'm trying to create a simple Carousel in Angular but the interaction part doesn't work , I didn't figure out the issue, can someone help me pls? When clicking on buttons they don't change the different pictures..

I tried to use ChatGpt and it doesn't help that much .. I'm expecting to make the interaction part work...

This is the code : slideshow.component.html :

<body>
    <div id="carousel-container">
        <div *ngIf="  images && images.length > 0" class="carousel-container">
          <div *ngFor="let image of images; let i = index">
            <img [src]="image.imagesrc" [alt]="image.imagealt"
                 [ngClass]="{'image-active': selectedIndex === i}"
                 (click)="selectImage(i)" class="fade">
         
        </div>
          <div *ngIf="indicators" class="carousel-dot-container">
            <span class="dot" *ngFor="let dot of images; let i = index"
                  [ngClass]="{'dot-active': selectedIndex === i}"
                  (click)="selectImage(i)">
            </span>
          </div>
          <a class="prev" (click)="previousSlide()">&#10094;</a>
          <a class="next" (click)="nextSlide()">&#10095;</a>
          
        </div>
    
      </div>

</body>
</html>  ,


slideshow.component.ts

import { Component, Input, OnInit } from '@angular/core';

import {  CommonModule } from '@angular/common'; 

interface SlideContent{
   imagesrc: string;
   imagealt: string;
   
}



@Component({
  selector: 'app-slideshow',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './slideshow.component.html',
  styleUrl: './slideshow.component.css'
})
export class SlideshowComponent implements OnInit {
  @Input() images: SlideContent[] = [];
  @Input() indicators = true;

  selectedIndex = 0;
   intervalId:any;

ngOnInit(): void {
  console.log('Slideshow initialized with images:', this.images);
}

//sets index of image on dot/indicator click
selectImage(index: number): void{

this.selectedIndex= index;
}


startAutoSlide() {
  this.intervalId = setInterval(() => {
    this.nextSlide();
  }, 3000); // Change slide every 3 seconds
}

nextSlide() {
  this.selectedIndex = (this.selectedIndex + 1) % this.images.length;
}

previousSlide() {
  this.selectedIndex = (this.selectedIndex - 1 + this.images.length) % this.images.length;
}
}

App.component.ts

images =[
 {
    imagesrc:'example',
     imagealt:"example",
 },
 {
  imagesrc: 'example',
   imagealt:"example",
},
{
  imagesrc:'example',
   imagealt:"example",
},

 }

And then in App.component.html: <app-slideshow [images]="images" [indicators]="true"></app-slideshow>

Error: NG0500: During hydration Angular expected but found meta.


Solution

  • The call to autoslide method, on ngOnInit hook was missing.

    I added one more input parameter for autoplay to enable it!

    Since you have SSR enabled, you can use the isPlatformBrowser to ensure the code runs only on the browser, since the server does not have document or window or setInterval

      ngAfterViewInit(): void {
        console.log('Slideshow initialized with images:', this.images);
        if (this.isBrowser) {
          if (this.autoplay) {
            this.startAutoSlide();
          }
        }
      }
    

    Full Code:

    import { CommonModule, isPlatformBrowser } from '@angular/common';
    import { Component, Inject, Input, PLATFORM_ID } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    
    interface SlideContent {
      imagesrc: string;
      imagealt: string;
    }
    
    @Component({
      selector: 'app-slideshow',
      standalone: true,
      imports: [CommonModule],
      styles: [
        `
      .fade {
        display: none;
      }
      .image-active {
        display: block;
      }
      `,
      ],
      template: `
      @defer {
        <div id="carousel-container">
            <div *ngIf="  images && images.length > 0" class="carousel-container">
              <div *ngFor="let image of images; let i = index">
                <img [src]="image.imagesrc" [alt]="image.imagealt"
                     [ngClass]="{'image-active': selectedIndex === i}"
                     (click)="selectImage(i)" class="fade">
             
            </div>
              <div *ngIf="indicators" class="carousel-dot-container">
                <span class="dot" *ngFor="let dot of images; let i = index"
                      [ngClass]="{'dot-active': selectedIndex === i}"
                      (click)="selectImage(i)">
                </span>
              </div>
              <a class="prev" (click)="previousSlide()">&#10094;</a>
              <a class="next" (click)="nextSlide()">&#10095;</a>
              
            </div>
        
          </div>
      }
      `,
    })
    export class SlideShow {
      @Input() images: SlideContent[] = [];
      @Input() indicators = true;
      @Input() autoplay = true;
    
      selectedIndex = 0;
      intervalId: any;
      isBrowser = false;
    
      constructor(@Inject(PLATFORM_ID) private _platformId: Object) {
        this.isBrowser = isPlatformBrowser(this._platformId);
      }
    
      ngAfterViewInit(): void {
        console.log('Slideshow initialized with images:', this.images);
        if (this.isBrowser) {
          if (this.autoplay) {
            this.startAutoSlide();
          }
        }
      }
    
      //sets index of image on dot/indicator click
      selectImage(index: number): void {
        this.selectedIndex = index;
      }
    
      startAutoSlide() {
        this.intervalId = setInterval(() => {
          this.nextSlide();
        }, 3000); // Change slide every 3 seconds
      }
    
      nextSlide() {
        this.selectedIndex = (this.selectedIndex + 1) % this.images.length;
      }
    
      previousSlide() {
        this.selectedIndex =
          (this.selectedIndex - 1 + this.images.length) % this.images.length;
      }
    }
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [SlideShow],
      template: `
        <app-slideshow [images]="images" [indicators]="true"></app-slideshow>
      `,
    })
    export class App {
      images = [
        {
          imagesrc: 'https://placehold.co/600x400/000000/FFFFFF/png?text=Slide+1',
          imagealt: 'example',
        },
        {
          imagesrc: 'https://placehold.co/600x400/000000/FFFFFF/png?text=Slide+2',
          imagealt: 'example',
        },
        {
          imagesrc: 'https://placehold.co/600x400/000000/FFFFFF/png?text=Slide+3',
          imagealt: 'example',
        },
      ];
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo