Search code examples
angularngoninitangular17

Using ngoninit doesn't load component


I am trying to implement a image-slider.

I have a image-slider componenent and a component in which i want to display the image slider I'd like to automatically slide through the images.

image-slider-component.html:

<div class="slides">
    <div
      class="slide"
      [ngStyle]="{
        'background-image': 'url(' + slides[currentSlide].url + ')',
        opacity: hidden ? 0 : 1,
        transition: 'opacity ' + animationSpeed + 'ms ease-in-out'
      }"
    ></div>
  
    @if (indicatorsVisible) {
    <div id="indicators">
      @for(slide of slides; track $index; ){
      <div
        (click)="jumpToSlide($index)"
        class="indicator"
        [ngClass]="{ active: $index == currentSlide }"
      ></div>
      }
    </div>
    }
  
    <button (click)="next()" class="nextButton">
      far
    </button>
    <button (click)="previous()" class="previousButton">
      back
    </button>
  </div>

image-slider-component.ts

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



@Component({
  selector: 'app-image-slider',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './image-slider.component.html',
  styleUrl: './image-slider.component.scss',
})
export class ImageSliderComponent implements OnInit{

  @Input() slides: any[] = [];
  @Input() indicatorsVisible = true;
  @Input() animationSpeed = 500;
  @Input() autoPlay = true;
  @Input() autoPlaySpeed = 3000;
  currentSlide = 0;
  hidden = false;

  next() {
    let currentSlide = (this.currentSlide + 1) % this.slides.length;
    this.jumpToSlide(currentSlide);
  }

  previous() {
    let currentSlide =
      (this.currentSlide - 1 + this.slides.length) % this.slides.length;
    this.jumpToSlide(currentSlide);
  }

  jumpToSlide(index: number) {
    this.hidden = true;
    setTimeout(() => {
      this.currentSlide = index;
      this.hidden = false;
    }, this.animationSpeed);
  }

  ngOnInit() {
    if (this.autoPlay) {
      setInterval(() => {
        this.next();
      }, this.autoPlaySpeed);
    }
  }

}

more.component.html (i'd like to display the img-slider here)

<div
  style="
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    padding: 20px;
    gap: 20px;
  "
>
  <app-image-slider
    [indicatorsVisible]="false"
    [animationSpeed]="100"
    [slides]="slides"
    [autoPlay]="true"
    [autoPlaySpeed]="5"
  ></app-image-slider>

  <app-image-slider
    [indicatorsVisible]="true"
    [animationSpeed]="400"
    [slides]="slides"
    [autoPlay]="true"
    [autoPlaySpeed]="5"
  ></app-image-slider>
</div>

more.component.ts (here are the imgs that are used by the img-slider)

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterOutlet } from '@angular/router';
import { ImageSliderComponent } from '../about/components/image-slider/image-slider.component';

@Component({
  selector: 'app-more',
  standalone: true,
  imports: [    CommonModule,
    RouterOutlet,
    FormsModule,
    ReactiveFormsModule,
    ImageSliderComponent,],
  templateUrl: './more.component.html',
  styleUrl: './more.component.scss'
})
export class MoreComponent {
  
  slides: any[] = [
    {
      url: 'https://html.com/wp-content/uploads/flamingo.webp',
      title: 'First Slide',
      description: 'test1',
    },
    {
      url: 'https://images.unsplash.com/photo-1542831371-29b0f74f9713?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aHRtbHxlbnwwfHwwfHx8MA%3D%3D',
      title: 'Second Slide',
      description: 'test2',
    }
  ];

  
}

The page doesnt load: enter image description here

If i remove the OnInit function aswell as the OnInit interface, the page is loading and i can switch through the images by the buttons i implemented, but the autoplay isn't working since I am not using the OnInit Function


Solution

  • import { Component, Input, OnInit, OnDestroy } from '@angular/core';
    import { CommonModule } from '@angular/common';
    
    @Component({
      selector: 'app-high-slider',
      standalone: true,
      imports: [CommonModule],
      templateUrl: './high-slider.component.html',
      styleUrl: './high-slider.component.scss'
    })
    export class HighSliderComponent implements OnInit, OnDestroy{
      @Input() slides!: any[];
      @Input() indicatorsVisible!: boolean;
      @Input() animationSpeed!: number; // Milliseconds
      @Input() autoPlay!: boolean;
      @Input() autoPlaySpeed!: number; // Milliseconds
    
      currentSlide = 0;
      autoPlayInterval?: number; // Use a more specific type for the interval ID
    
      constructor() { }
    
      ngOnInit(): void {
        if (this.autoPlay) {
          this.setupAutoPlay();
        }
      }
    
      ngOnDestroy(): void {
        this.clearAutoPlay();
      }
    
      next(): void {
        this.currentSlide = (this.currentSlide + 1) % this.slides.length;
      }
    
      previous(): void {
        this.currentSlide = (this.currentSlide - 1 + this.slides.length) % this.slides.length;
      }
    
      jumpToSlide(index: number): void {
        this.currentSlide = index;
      }
    
      private setupAutoPlay(): void {
        // Check if running in the browser environment
        if (typeof window !== 'undefined') {
          this.autoPlayInterval = window.setInterval(() => this.next(), this.autoPlaySpeed);
        }
      }
      private clearAutoPlay(): void {
        if (typeof window !== 'undefined' && this.autoPlayInterval) {
          clearInterval(this.autoPlayInterval);
        }
      }
    
    }