Search code examples
javascriptaddeventlistenerqueryselectorouterhtml

Event Listener does not work if I change outerHTML


I have 3 images in html.
I select the images with querySelectorAll, turn them into an array, and:

Step1
I enclose them inside a <div> tag, adding an .img-container class, using outerHTML.

Step2
I add an Event Listener to the images. When the images are clicked, I console log "img has been clicked".

If I run Step1 alone, the code works.
If I run Step2 alone, the code works.

When I try to run both Step1 and Step2, the Event Listener (Step 2) does not work.

Any help?

// Select all img tags
const allImg = document.querySelectorAll('img');


// ***STEP 1 ***
//Enclose imgs in divs (and add img-container class)
const allImgArr = Array.from(allImg).map((curr) =>
  curr.outerHTML = '<div class="img-container">' + curr.outerHTML + '</div>' );

// ***STEP 2***
//Click on image to console.log 'img has been clicked'
const allImgArrTwo = Array.from(allImg).map((curr) =>
  curr.addEventListener('click', function() {
      console.log ('img has been clicked')
    }));
.img-container {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: red;
    width: 250px;
    height: 250px;
}
<p>Img 1</p>
<img src="https://images.pexels.com/photos/574071/pexels-photo-574071.jpeg" width="100" height="100" alt="">


<p>Img 2</p>
<img src="https://images.pexels.com/photos/1181676/pexels-photo-1181676.jpeg" width="100" height="100"  alt="">

<p>Img 3</p>
<img src="https://images.pexels.com/photos/1181244/pexels-photo-1181244.jpeg" width="100" height="100" alt="">


Solution

  • You do not need to add event listeners to every image. Using event delegation should solve your problem. That makes the second step superfluous. The snippet demonstrates event delegation and a way to create elements without the need for outerHTML.

    Fork this stackblitz project to play with this code.

    document.addEventListener(`click`, evt => {
      if (evt.target.nodeName === `IMG`) {
        console.clear();
        console.log(`image has been clicked`);
      }
    });
    
    // No steps needed.
    // Alternative for creating div.img-container for each image
    // (avoids outerHTML).
    document.querySelectorAll('img').forEach( img => 
      img.insertAdjacentElement( `beforebegin`, 
        Object.assign(document.createElement(`div`), {className: `img-container`}) )
      .appendChild(img)
    );
    .img-container {
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: red;
        width: 250px;
        height: 250px;
    }
    <p>Img 1</p>
    <img src="//images.pexels.com/photos/574071/pexels-photo-574071.jpeg?cs=srgb&dl=pexels-lukas-574071.jpg" width="100" height="100" alt="">
    
    
    <p>Img 2</p>
    <img src="//images.pexels.com/photos/1181676/pexels-photo-1181676.jpeg?cs=srgb&dl=pexels-christina-morillo-1181676.jpg" width="100" height="100"  alt="">
    
    <p>Img 3</p>
    <img src="//images.pexels.com/photos/1181244/pexels-photo-1181244.jpeg" width="100" height="100" alt="">