skip to Main Content

Here is a a demo application code to show images in a carousel. It works well with static images. But I want to add images to the carousel dynamically on a button click.

I added images on a button click, and it adds it in the container, which I can see if I debug the page using the browser’s Developer Tools. But the image is not shown in the carousel.

Reference CodePen link

document.addEventListener("DOMContentLoaded", function() {
  let carousel = document.querySelector(".carousel");
  let items = carousel.querySelectorAll(".item");

  // Function to show a specific item
  function showItem(index) {
    items.forEach((item, idx) => {
      item.classList.remove("active");
      if (idx === index) {
        item.classList.add("active");
      }
    });
  }

  // Event listeners for buttons
  document.querySelector(".prev").addEventListener("click", () => {
    let index = [...items].findIndex((item) =>
      item.classList.contains("active")
    );
    showItem((index - 1 + items.length) % items.length);
  });

  document.querySelector(".next").addEventListener("click", () => {
    let index = [...items].findIndex((item) =>
      item.classList.contains("active")
    );
    showItem((index + 1) % items.length);
  });
});

//I tried the following function:
function buttonClicked() {
  const carouselContainer = document.querySelector('.carousel');

  // Create the carousel item
  const carouselItemContainer = document.createElement('div');
  carouselItemContainer.classList.add('item');

  // Create image element
  const imageElement = document.createElement('img');
  imageElement.src = "image URL";
  imageElement.alt = "test image";
  imageElement.classList.add("active");

  // Add a title below the image
  const imageTitle = document.createElement('p');
  imageTitle.textContent = "title of test image";
  imageTitle.classList.add('caption');

  carouselItemContainer.appendChild(imageElement);
  carouselItemContainer.appendChild(imageTitle);
  carouselContainer.appendChild(carouselItemContainer);
}
body {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  font-family: "Satoshi", sans-serif;
  font-size: var(--lx-text-01);
  font-weight: 500;
  color: #ffffe6;
  background-color: #10100e;
}

.carousel-container {
  width: 80%;
  margin: auto;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--lx-gap);

  .carousel {
    aspect-ratio: 16/9;
    width: 100%;
    position: relative;
    overflow: hidden;

    .item {
      opacity: 0;
      width: 100%;
      height: 100%;
      display: none;
      transition: opacity 0.5s ease-in-out;

      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: center;
      }

      .caption {
        width: 100%;
        padding: var(--lx-space-01);
        position: absolute;
        bottom: 0;
        text-transform: uppercase;
        text-align: center;
        font-size: 12px;
        background-color: rgba(0, 0, 0, 0.5);
      }

      &.active {
        opacity: 1;
        display: block;
      }
    }
  }

  .btn {
    padding: 1em 2em;
    position: absolute;
    transform: translateY(-50%);
    top: 50%;
    outline: none;
    border: none;
    cursor: pointer;
    text-transform: uppercase;
    font-size: 12px;
    font-weight: 900;
    color: #10100e;
    background-color: #ffffe6;
    transition: transform 0.2s ease-in-out;

    &:active,
    &:focus {
      transform: translateY(-50%) scale(0.9);
    }

    &:hover {
      transform: translateY(-50%) scale(0.96);
    }
  }

  .prev {
    left: -5%;
  }

  .next {
    right: -5%;
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>Image Slider</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" />

  <link rel="stylesheet" href="style - copy.css" />
  <script src="script - copy.js"></script>
</head>

<body>
  <main class="carousel-container">
  <div class="carousel">
    <div class="item active">
      <img src="https://images.unsplash.com/photo-1457732815361-daa98277e9c8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" alt="Image 1" />
      <p class="caption">Caption for Image 1</p>
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1500206329404-5057e0aefa48?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1355&amp;q=80" alt="Image 2" />
      <p class="caption">Caption for Image 2</p>
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1502239608882-93b729c6af43?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1350&amp;q=80" alt="Image 3" />
      <p class="caption">Caption for Image 3</p>
    </div>
  </div>
  <button class="btn prev">Prev</button>
  <button class="btn next">Next</button>
  <div class="dots"></div>
</main>
</body>

</html>

It adds the image to the carousel container but the image is not displayed in the carousel.

2

Answers


  1. Because the "next" and "prev" buttons in your code find the next image from the items array (rather than reading direct from the carousel container elemente each time), you need to ensure you re-initialise items after you’ve added the new image, by reading the list of elements from the carousel container again.

    Once you add that step, your code works fine – demo:

    document.addEventListener("DOMContentLoaded", function() {
      let carousel = document.querySelector(".carousel");
      let items = carousel.querySelectorAll(".item");
    
      // Function to show a specific item
      function showItem(index) {
        items.forEach((item, idx) => {
          item.classList.remove("active");
          if (idx === index) {
            item.classList.add("active");
          }
        });
      }
    
      // Event listeners for buttons
      document.querySelector(".prev").addEventListener("click", () => {
        let index = [...items].findIndex((item) =>
          item.classList.contains("active")
        );
        showItem((index - 1 + items.length) % items.length);
      });
    
      document.querySelector(".next").addEventListener("click", () => {
        let index = [...items].findIndex((item) =>
          item.classList.contains("active")
        );
        showItem((index + 1) % items.length);
      });
    
      document.querySelector("#addImage").addEventListener("click", function(e) {
        const carouselContainer = document.querySelector('.carousel');
    
        // Create the carousel item
        const carouselItemContainer = document.createElement('div');
        carouselItemContainer.classList.add('item');
    
        // Create image element
        const imageElement = document.createElement('img');
        imageElement.src = "https://i.imgur.com/db4KgSp.png";
        imageElement.alt = "test image";
        imageElement.classList.add("active");
    
        // Add a title below the image
        const imageTitle = document.createElement('p');
        imageTitle.textContent = "title of test image";
        imageTitle.classList.add('caption');
    
        carouselItemContainer.appendChild(imageElement);
        carouselItemContainer.appendChild(imageTitle);
        carouselContainer.appendChild(carouselItemContainer);
        items = carousel.querySelectorAll(".item");
      });
    
    });
    body {
      min-height: 100dvh;
      display: flex;
      align-items: center;
      font-family: "Satoshi", sans-serif;
      font-size: var(--lx-text-01);
      font-weight: 500;
      color: #ffffe6;
      background-color: #10100e;
    }
    
    .carousel-container {
      width: 80%;
      margin: auto;
      position: relative;
      display: flex;
      flex-direction: column;
      gap: var(--lx-gap);
    
      .carousel {
        aspect-ratio: 16/9;
        width: 100%;
        position: relative;
        overflow: hidden;
    
        .item {
          opacity: 0;
          width: 100%;
          height: 100%;
          display: none;
          transition: opacity 0.5s ease-in-out;
    
          img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            object-position: center;
          }
    
          .caption {
            width: 100%;
            padding: var(--lx-space-01);
            position: absolute;
            bottom: 0;
            text-transform: uppercase;
            text-align: center;
            font-size: 12px;
            background-color: rgba(0, 0, 0, 0.5);
          }
    
          &.active {
            opacity: 1;
            display: block;
          }
        }
      }
    
      .btn {
        padding: 1em 2em;
        position: absolute;
        transform: translateY(-50%);
        top: 50%;
        outline: none;
        border: none;
        cursor: pointer;
        text-transform: uppercase;
        font-size: 12px;
        font-weight: 900;
        color: #10100e;
        background-color: #ffffe6;
        transition: transform 0.2s ease-in-out;
    
        &:active,
        &:focus {
          transform: translateY(-50%) scale(0.9);
        }
    
        &:hover {
          transform: translateY(-50%) scale(0.96);
        }
      }
    
      .prev {
        left: -5%;
      }
    
      .next {
        right: -5%;
      }
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <title>Image Slider</title>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" />
    
      <link rel="stylesheet" href="style - copy.css" />
      <script src="script - copy.js"></script>
    </head>
    
    <body>
      <div><button type="button" id="addImage">Add Image</button></div>
      <main class="carousel-container">
        <div class="carousel">
          <div class="item active">
            <img src="https://images.unsplash.com/photo-1457732815361-daa98277e9c8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" alt="Image 1" />
            <p class="caption">Caption for Image 1</p>
          </div>
          <div class="item">
            <img src="https://images.unsplash.com/photo-1500206329404-5057e0aefa48?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1355&amp;q=80" alt="Image 2" />
            <p class="caption">Caption for Image 2</p>
          </div>
          <div class="item">
            <img src="https://images.unsplash.com/photo-1502239608882-93b729c6af43?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1350&amp;q=80" alt="Image 3" />
            <p class="caption">Caption for Image 3</p>
          </div>
        </div>
        <button class="btn prev">Prev</button>
        <button class="btn next">Next</button>
        <div class="dots"></div>
      </main>
    </body>
    
    </html>
    Login or Signup to reply.
  2. Instead of relying on indexes and (global’ich) variables you can selecte the next/previous images based on the current active image. And when adding a new image you can just use that reference to display the image.

    document.addEventListener("DOMContentLoaded", function() {
      // Event listeners for buttons
      document.querySelector(".carousel-container").addEventListener("click", carouselBtnHandler);
      document.querySelector("#addImage").addEventListener("click", addImageHandler);
    });
    
    // Function to show a specific item
    function showItem(elm) {
      elm.closest('.carousel').querySelectorAll(".item")
        .forEach(item => item.classList.remove("active"));
      elm.classList.add('active');
    }
    
    // Function for handling click events on buttons on the carousel
    function carouselBtnHandler(e) {
      let carousel = e.target.closest('.carousel-container').querySelector('.carousel');
      let activeElm = carousel.querySelector('.active');
      switch(e.target.name){
        case 'prev':
         showItem(activeElm.previousElementSibling ?? carousel.lastElementChild);
          break;
        case 'next':
          showItem(activeElm.nextElementSibling ?? carousel.firstElementChild);
          break;
      }
    }
    
    // Function for adding image
    function addImageHandler(e) {
      const carouselContainer = document.querySelector('.carousel');
    
      // Create the carousel item
      const carouselItemContainer = document.createElement('div');
      carouselItemContainer.classList.add('item');
    
      // Create image element
      const imageElement = document.createElement('img');
      
      imageElement.alt = "test image";
      imageElement.classList.add("active");
    
      // Add a title below the image
      const imageTitle = document.createElement('p');
      imageTitle.textContent = "title of test image";
      imageTitle.classList.add('caption');
    
      carouselItemContainer.appendChild(imageElement);
      carouselItemContainer.appendChild(imageTitle);
      carouselContainer.appendChild(carouselItemContainer);
      
      // Show the new image
      imageElement.addEventListener('load', e => {
        showItem(e.target.closest('.item'));
      });
      imageElement.src = "https://i.imgur.com/db4KgSp.png";
    
    }
    body {
      min-height: 100dvh;
      display: flex;
      align-items: center;
      font-family: "Satoshi", sans-serif;
      font-size: var(--lx-text-01);
      font-weight: 500;
      color: #ffffe6;
      background-color: #10100e;
    }
    
    .carousel-container {
      width: 80%;
      margin: auto;
      position: relative;
      display: flex;
      flex-direction: column;
      gap: var(--lx-gap);
    
      .carousel {
        aspect-ratio: 16/9;
        width: 100%;
        position: relative;
        overflow: hidden;
    
        .item {
          opacity: 0;
          width: 100%;
          height: 100%;
          display: none;
          transition: opacity 0.5s ease-in-out;
    
          img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            object-position: center;
          }
    
          .caption {
            width: 100%;
            padding: var(--lx-space-01);
            position: absolute;
            bottom: 0;
            text-transform: uppercase;
            text-align: center;
            font-size: 12px;
            background-color: rgba(0, 0, 0, 0.5);
          }
    
          &.active {
            opacity: 1;
            display: block;
          }
        }
      }
    
      .btn {
        padding: 1em 2em;
        position: absolute;
        transform: translateY(-50%);
        top: 50%;
        outline: none;
        border: none;
        cursor: pointer;
        text-transform: uppercase;
        font-size: 12px;
        font-weight: 900;
        color: #10100e;
        background-color: #ffffe6;
        transition: transform 0.2s ease-in-out;
    
        &:active,
        &:focus {
          transform: translateY(-50%) scale(0.9);
        }
    
        &:hover {
          transform: translateY(-50%) scale(0.96);
        }
      }
    
      .prev {
        left: -5%;
      }
    
      .next {
        right: -5%;
      }
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <title>Image Slider</title>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" />
    
      <link rel="stylesheet" href="style - copy.css" />
      <script src="script - copy.js"></script>
    </head>
    
    <body>
      <div><button type="button" id="addImage">Add Image</button></div>
      <main class="carousel-container">
        <div class="carousel">
          <div class="item active">
            <img src="https://images.unsplash.com/photo-1457732815361-daa98277e9c8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" alt="Image 1" />
            <p class="caption">Caption for Image 1</p>
          </div>
          <div class="item">
            <img src="https://images.unsplash.com/photo-1500206329404-5057e0aefa48?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1355&amp;q=80" alt="Image 2" />
            <p class="caption">Caption for Image 2</p>
          </div>
          <div class="item">
            <img src="https://images.unsplash.com/photo-1502239608882-93b729c6af43?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1350&amp;q=80" alt="Image 3" />
            <p class="caption">Caption for Image 3</p>
          </div>
        </div>
        <button name="prev" class="btn prev">Prev</button>
        <button name="next" class="btn next">Next</button>
        <div class="dots"></div>
      </main>
    </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search