Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the click event inside an innerHTML?

I've this layout that was created dynamically:

for (let i = 1; i < 10; i++) {
  document.querySelector('.card-body').innerHTML += `<div class="row" id="img_div">
        <div class="col-12 col-sm-12 col-md-2 text-center">
          <img src="http://placehold.it/120x80" alt="prewiew" width="120" height="80">
        </div>
        <div id="text_div" class="col-12 text-sm-center col-sm-12 text-md-left col-md-6">
        <h4 class="name"><a href="#" id="title` + i + `">Name</a></h4>
          <h4>
            <small>state</small>
          </h4>
          <h4>
            <small>city</small>
          </h4>
          <h4>
            <small>zip</small>
          </h4>
        </div>
        <div class="col-12 col-sm-12 text-sm-center col-md-4 text-md-right row">
        </div>
      </div>
     `
  document.getElementById("title" + i).addEventListener('click', function() {
    console.log(i)
  });
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="card-body">
  <!-- person -->
</div>

And I want to get the event click on each h4 class="name" and show a log with the number i related.

However, console.log shows only the last i related (i=9 in this case), and doesn't work with the other i numbers. Why does this happen? What do I have to do?

like image 695
Luiz Adorno Avatar asked Feb 14 '20 22:02

Luiz Adorno


People also ask

How do I get the innerHTML of a clicked element?

onclick = function(event) { var target = event. target || event. srcElement; alert ( target. innerHTML ); };

How do you add onclick to innerHTML?

innerHTML = '<div id=\"a\">Test onclick</div>'; document. getElementById('a'). onclick = function() { alert("Click Event Fired !") }

How do I find the click event in my browser?

You can detect clicks inside the page with a simple click event handler: document. onclick= function(event) { // Compensate for IE<9's non-standard event model // if (event===undefined) event= window.

Why you shouldn't use innerHTML?

The use of innerHTML creates a potential security risk for your website. Malicious users can use cross-site scripting (XSS) to add malicious client-side scripts that steal private user information stored in session cookies. You can read the MDN documentation on innerHTML .


2 Answers

Using += on innerHTML destroys event listeners on the elements inside the HTML. The correct way to do this is to use document.createElement. Here's a minimal, complete example:

for (let i = 1; i < 10; i++) {
  const anchor = document.createElement("a");
  document.body.appendChild(anchor);
  anchor.id = "title" + i;
  anchor.href= "#";
  anchor.textContent = "link " + i;
  document.getElementById("title" + i)
    .addEventListener("click", e => console.log(i));
}
a {
  margin-left: 0.3em;
}

Of course, the document.getElementById isn't necessary here since we just created the object in the loop block. This saves potentially expensive tree walks.

for (let i = 1; i < 10; i++) {
  const anchor = document.createElement("a");
  document.body.appendChild(anchor);    
  anchor.href= "#";
  anchor.textContent = "link " + i;
  anchor.addEventListener("click", e => console.log(i));
}
a {
  margin-left: 0.3em;
}

If you have arbitrary chunks of stringified HTML as in your example, you can use createElement("div"), set its innerHTML once to the chunk and add listeners as needed. Then append the divs as children of your container element.

for (let i = 1; i < 10; i++) {
  const rawHTML = `<div><a href="#" id="link-${i}">link ${i}</a></div>`;
  const div = document.createElement("div");
  document.body.appendChild(div);
  div.href= "#";
  div.innerHTML = rawHTML;
  div.querySelector(`#link-${i}`)
    .addEventListener("click", e => console.log(i));
}
like image 193
ggorlen Avatar answered Sep 24 '22 15:09

ggorlen


innerHTML redraws the full html, as a result all the previously attached events are lost. Use insertAdjacentHTML()

for(let i=1;i<10;i++){
    document.querySelector('.card-body').insertAdjacentHTML('beforeend',`<div class="row" id="img_div">
        <div class="col-12 col-sm-12 col-md-2 text-center">
          <img src="http://placehold.it/120x80" alt="prewiew" width="120" height="80">
        </div>
        <div id="text_div" class="col-12 text-sm-center col-sm-12 text-md-left col-md-6">
        <h4 class="name"><a href="#" id="title`+i+`">Name</a></h4>
          <h4>
            <small>state</small>
          </h4>
          <h4>
            <small>city</small>
          </h4>
          <h4>
            <small>zip</small>
          </h4>
        </div>
        <div class="col-12 col-sm-12 text-sm-center col-md-4 text-md-right row">
        </div>
      </div>
     `);
   document.getElementById("title"+i).addEventListener('click', function () {
    console.log(i)
  });
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="card-body">
<!-- person -->
</div>
like image 25
Mamun Avatar answered Sep 22 '22 15:09

Mamun