gareth power
gareth power

Reputation: 229

Javascript EventListener disappears when another is created

I am trying to create a script where a select HTML object detects a change, gets its value and creates another tag to display based on its value. E.g. A user selects 'United Kingdom' and a tag saying that appears in the div. This works, but I have an X-button for it that deletes the tag when clicked, using an EventListener. The problem is that I can only ever delete the final tag created, as the variables used to create each tag's id change, and so, only the last one works. Some of the code is below:

 document.getElementById("locations-editor-container1").innerHTML = 
    document.getElementById("locations-editor-container1").innerHTML+"<div 
    class='locations-editor-country-disp' id='"+country+"[@]'>"+country+"<svg  
   id='"+country+"[##]' class='locations-editor-x-button' 
   style='width:2vh;position:absolute;right:0.5vw;vertical-align:middle;' 
   viewBox='0 0 24 24'><path fill='#FFFFFF' 


      d='M19,6.41L17.59,5L12,10.59L6.41,
      5L5,6.41L10.59, 12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z'/></svg></div><br>";
            var countryId=country+"[##]";
            
     document.getElementById(countryId).addEventListener("click",function(){ remove(countryId)},false);

Upvotes: 0

Views: 483

Answers (1)

HMR
HMR

Reputation: 39250

Below is your error reproduced, because you are replacing innerHTML of some content you are removing the event listeners of the elements you are replacing. That is why only the last element works:

const content = document.querySelector("#content");
var counter = 0;
const add = e => {
  content.innerHTML = 
      //you are replacing content, thus removing the event listeners of 
      //  previous elements
      content.innerHTML +
    `<div style="cursor: pointer;" id="div${++counter}">
        click me ${counter}
    </div>`;
  document.querySelector(`#div${counter}`)
  .addEventListener(
    "click"
    ,(x=>e=>{
      alert(`Counter for this div:${x}`);
    })(counter)
  );
}
document.querySelector("#myButton").addEventListener(
  "click"
  ,add
);
<div id="content">
</div>
<input type="button" id="myButton" value="add">

The solution is to not replace the content but add the new item to existing content:

    const content = document.querySelector("#content");
    var counter = 0;
    const add = e => {
      //create a div (will not be added to dom yet)
      const div = document.createElement("div");
      div.innerHTML = 
        `<div style="cursor: pointer;" id="div${++counter}">
          click me ${counter}
        </div>`;
      div
      .addEventListener(
        "click"
        ,(x=>e=>{
          alert(`Counter for this div:${x}`);
        })(counter)
      );
      //add element to dom (do not replace content)
      content.appendChild(div);
    }
    document.querySelector("#myButton").addEventListener(
      "click"
      ,add
    );
    <div id="content">
    </div>
    <input type="button" id="myButton" value="add">

Upvotes: 2

Related Questions