3

I dont understand why addEventListener work once?

let input = document.querySelector(".send");
let i = 0;

input.addEventListener('click',(e)=>{
   e.preventDefault();
   i+=1;
   document.body.innerHTML += i;
});
<input type="submit" class="send">
Rso Invisible
  • 73
  • 1
  • 8

2 Answers2

5

This is because of this line:

document.body.innerHTML

that "removes" the former set listener. You actually alter the html in a way that this listener loses track of the input-element.

You could use createTextNode to fix this or createElement and appendChild to use a newly created HTML-Node instead:

var input = document.querySelector(".send");

var i = 0;

input.addEventListener('click',function(e){
   e.preventDefault();
   i+=1;
   // option 1: use a new node, but in order to prevent the same innerHTML bug again use option 2 instead
   //var newNode = document.createElement("span");
   //newNode.innerHTML = i;
   //document.body.appendChild(newNode);
   // option 2 use createTextNode so that innerHTML is not used at all
   document.body.appendChild(document.createTextNode(i));
});
<input type="submit" class="send">
Blauharley
  • 4,186
  • 6
  • 28
  • 47
1

This code will behave the way you would like:

let input = document.querySelector(".send");
let result = document.querySelector("#result");

let i = 0;

input.addEventListener('click', (e)=>{
   e.preventDefault();
   i += 1;
   result.innerHTML += i;
})
<input type="submit" class="send">
<div id="result"></div>

You should not edit the innerHTML of the body itself. Instead, try targeting elements within your body.

  • You probably should not edit `innerHTML` at all. Anywhere. – Bergi May 20 '18 at 19:49
  • Is that true? I've seen that before, but I've seen just as many posts saying that it's usually okay. Have a good source on why you should never use it? – Michael Karpinski May 20 '18 at 20:11
  • I might have exaggerated, but it's really rare theses days that you need to handler raw HTML strings with JS these days (for which it might be ok). But here we want to put numbers (i.e. **text**) in an element, so `innerHTML` should definitely avoided. `textContent` should be the default to use. – Bergi May 20 '18 at 20:18
  • I never knew about `textContent`. That is very helpful, thanks! – Michael Karpinski May 20 '18 at 20:39