3

I am trying to implement a image slider in angular from scratch, and trying to replicate a w3school based image slider.

Below I have tried to implement in angular, Can anyone guide me how to implement using angular?

Here you can find stackblitz link

component.html

<div class="slideshow-container" #myDiv>

    <div class="mySlides fade">
        <div class="numbertext">1 / 3</div>
        <img src="https://img.adaptivereso.com/https://stellarmls-propertyresi.s3.us-west-002.backblazeb2.com/314a10f7-07d4-4d9e-b8ea-be44be55ab35.jpeg/?rwidth=300&rheight=200&type=jpg" style="width:100%">
        <div class="text">Caption Text</div>
    </div>

    <div class="mySlides fade" >
        <div class="numbertext">2 / 3</div>
        <img src="https://img.adaptivereso.com/https://stellarmls-propertyresi.s3.us-west-002.backblazeb2.com/cd7c5e85-d528-4d10-a635-ace77aaef77d.jpeg/?rwidth=300&rheight=200&type=jpg" style="width:100%">
        <div class="text">Caption Two</div>
    </div>

    <div class="mySlides fade">
        <div class="numbertext">3 / 3</div>
        <img src="https://img.adaptivereso.com/https://stellarmls-propertyresi.s3.us-west-002.backblazeb2.com/314a10f7-07d4-4d9e-b8ea-be44be55ab35.jpeg/?rwidth=300&rheight=200&type=jpg" style="width:100%">
        <div class="text">Caption Three</div>
    </div>

    <a class="prev" (click)="plusSlides(-1)">&#10094;</a>
    <a class="next" (click)="plusSlides(1)">&#10095;</a>

</div>
<br>

<div style="text-align:center">
    <span class="dot" (click)="currentSlide(1)"></span>
    <span class="dot" (click)="currentSlide(2)"></span>
    <span class="dot" (click)="currentSlide(3)"></span>
</div>

component.ts

import { Component, OnInit, ViewChild, ElementRef, ViewChildren, QueryList } from '@angular/core';

@Component({
  selector: 'app-custom-gallery',
  templateUrl: './custom-gallery.component.html',
  styleUrls: ['./custom-gallery.component.css']
})
export class CustomGalleryComponent implements OnInit {

  slideIndex:number = 1;
  constructor (public elementRef: ElementRef) { }

  ngOnInit(): void {
    this.showSlides(this.slideIndex);
  }

  plusSlides(n) {
    this.showSlides(this.slideIndex += n);
  }
  
  currentSlide(n) {
    console.log(n)
    this.showSlides(this.slideIndex = n);
  }

  showSlides(n) {
    var i;
    var slides = document.getElementsByClassName("mySlides");
    var dots = document.getElementsByClassName("dot");
    if (n > slides.length) {this.slideIndex = 1}    
    if (n < 1) {this.slideIndex = slides.length}
    for (i = 0; i < slides.length; i++) {
      console.log(typeof slides[i]);
        // slides[i].style.display = "none";
    }
    for (i = 0; i < dots.length; i++) {
        dots[i].className = dots[i].className.replace(" active", "");
    }
    // slides[this.slideIndex-1].style.display = "block";  
    dots[this.slideIndex-1].className += " active";
  }

}

component.css

* {box-sizing: border-box}
body {font-family: Verdana, sans-serif; margin:0}
.mySlides {display: none}
img {vertical-align: middle;}

/* Slideshow container */
.slideshow-container {
  max-width: 1000px;
  position: relative;
  margin: auto;
}

/* Next & previous buttons */
.prev, .next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  padding: 16px;
  margin-top: -22px;
  color: white;
  font-weight: bold;
  font-size: 18px;
  transition: 0.6s ease;
  border-radius: 0 3px 3px 0;
  user-select: none;
}

/* Position the "next button" to the right */
.next {
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
  background-color: rgba(0,0,0,0.8);
}

/* Caption text */
.text {
  color: #f2f2f2;
  font-size: 15px;
  padding: 8px 12px;
  position: absolute;
  bottom: 8px;
  width: 100%;
  text-align: center;
}

/* Number text (1/3 etc) */
.numbertext {
  color: #f2f2f2;
  font-size: 12px;
  padding: 8px 12px;
  position: absolute;
  top: 0;
}

/* The dots/bullets/indicators */
.dot {
  cursor: pointer;
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

.active, .dot:hover {
  background-color: #717171;
}

/* Fading animation */
.fade {
  -webkit-animation-name: fade;
  -webkit-animation-duration: 1.5s;
  animation-name: fade;
  animation-duration: 1.5s;
}

@-webkit-keyframes fade {
  from {opacity: .4} 
  to {opacity: 1}
}

@keyframes fade {
  from {opacity: .4} 
  to {opacity: 1}
}

/* On smaller screens, decrease text size */
@media only screen and (max-width: 300px) {
  .prev, .next,.text {font-size: 11px}
}
4
  • Does your stackblitz do anything? I just get 3 dots. Commented Jul 16, 2021 at 10:10
  • @wlf it's showing 3 dots, So this is the error i am getting, but expected output should be image slider Commented Jul 16, 2021 at 10:37
  • Its not showing anything because you have display: none; on all of the images. But I don't think your general approach is correct. You want an ImageSliderComponent, one approach would be to have it take the images as an input array. The component would encapsulate functionality for navigating between the images etc. Commented Jul 16, 2021 at 10:48
  • So initailly i am making all as display none then on click of arrow one by one image will show. slides[i].style.display = "none" i am getting error here Commented Jul 16, 2021 at 11:03

2 Answers 2

2

Here is an approach you could use:

Create an ImageSlider component, which takes a list of images as in an input, and keeps track of the current slide

export class ImageSliderComponent {
  @Input() images: string[];

  slideIndex: number = 0;

  changeSlide(n: number) {
    this.slideIndex += n;
  }
}

In the template, display only the active slide (refer to the img src binding):

<div class="slideshow-container" #myDiv>
  <div class="mySlides fade">
    <div class="numbertext">{{ slideIndex + 1}} / {{ images.length }}</div>
    <img
    [src]="images[slideIndex]" 
    style="width:100%"
  />
    <div class="text">Caption Text</div>
  </div>

  <a class="prev" (click)="changeSlide(-1)">&#10094;</a>
  <a class="next" (click)="changeSlide(1)">&#10095;</a>
</div>

Use your component like:

<app-image-slider [images]="[
  'http://images.com/image1.jpg',
  'http://images.com/image1.jpg',
  'http://images.com/image3.jpg']"></app-image-slider>

Stackblitz: https://stackblitz.com/edit/angular-ivy-x9nk16?file=src%2Fapp%2Fimage-slider.component.ts

Note:

  • avoid use of ElementRef, getElementsByClassName, etc in Angular applications, this is usually an indication you are not using Angular conventions.
Sign up to request clarification or add additional context in comments.

Comments

0

Here is an approach you could use:

Create an ImageSlider component, which takes a list of images as in an input, and keeps track of the current slide

export class ImageSliderComponent {
  @Input() images: string[];

  slideIndex: number = 0;

  changeSlide(n: number) {
    this.slideIndex += n;
  }
}
In the template, display only the active slide (refer to the img src binding):

<div class="slideshow-container" #myDiv>
  <div class="mySlides fade">
    <div class="numbertext">{{ slideIndex + 1}} / {{ images.length }}</div>
    <img
    [src]="images[slideIndex]" 
    style="width:100%"
  />
    <div class="text">Caption Text</div>
  </div>

  <a class="prev" (click)="changeSlide(-1)">&#10094;</a>
  <a class="next" (click)="changeSlide(1)">&#10095;</a>
</div>

Use your component like:

<app-image-slider [images]="[
  'http://images.com/image1.jpg',
  'http://images.com/image1.jpg',
  'http://images.com/image3.jpg']"></app-image-slider>

https://stackblitz.com/edit/angular-ivy-xppajp?file=src%2Fapp%2Fimage-slider.component.ts

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.