Using ngoninit doesn't load component

93 Views Asked by At

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

2

There are 2 best solutions below

1
SoXCodinJava On BEST ANSWER
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);
    }
  }

}
1
Eliseo On

See that you don't clear the interval, so you early can have several intervals running.

Check also you have an interval like "5" milliseconds!!! and that when you execute jumpToSlide are "living" almost the autoplay and the another setTimeOut.

You need store in a variable your interval

interval:!any;

Create two functions: startInterval and clearInterval

startInterval()
{
   this.interval=setInterval(() => {
        this.next();
      }, this.autoPlaySpeed);
}

stopInterval()
{
   clearInterval(this.interval);
   this.interval= null;
}

Then,

  1. you call to startInterval in ngOnInit
  2. you call to stopInterval at start jumpToSlide and startInterval at end jumToSlide
  3. you call to stopInterval in ngOnDestroy
  4. you can also call to stopInterval in a mouseEnter and a startInterval in a mouseOut