最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I add event listener to dynamic element Id? - Stack Overflow

programmeradmin0浏览0评论

I am using firebase DB to dynamically generate some html using the function below.

function Inventorytable(data) {
  var container = document.getElementById('iteminfo'); 
  container.innerHTML = '';

  data.forEach(function(InventSnap) { // loop over all jobs
    var key = InventSnap.key;
    var Items = InventSnap.val();
    var jobCard = `
      <td class="text-left" id="${key}"><a href>${key}</a href></td>
      <td class="text-left" >${Items.PartNumber}</td>
    `;
    container.innerHTML += jobCard;
  })
}

I want to add an event listener to the first td class with id="${key}". I know with a normal id I can use document.getElementById("xxxx").addEventListener but since this is dynamic and the id is the firebase key. How do I add an event listener using the element id?

I am using firebase DB to dynamically generate some html using the function below.

function Inventorytable(data) {
  var container = document.getElementById('iteminfo'); 
  container.innerHTML = '';

  data.forEach(function(InventSnap) { // loop over all jobs
    var key = InventSnap.key;
    var Items = InventSnap.val();
    var jobCard = `
      <td class="text-left" id="${key}"><a href>${key}</a href></td>
      <td class="text-left" >${Items.PartNumber}</td>
    `;
    container.innerHTML += jobCard;
  })
}

I want to add an event listener to the first td class with id="${key}". I know with a normal id I can use document.getElementById("xxxx").addEventListener but since this is dynamic and the id is the firebase key. How do I add an event listener using the element id?

Share Improve this question edited Aug 31, 2017 at 7:40 Rory McCrossan 338k41 gold badges320 silver badges351 bronze badges asked Aug 31, 2017 at 7:33 e.ilufe.iluf 1,6697 gold badges32 silver badges82 bronze badges 5
  • 1 You can add a class that dynamic div and then add event Listener to that class – Naveed Ramzan Commented Aug 31, 2017 at 7:38
  • Put the document.getElementById('${key}').addEventListener inside jobCard... <script>HERE</script> – Roy Bogado Commented Aug 31, 2017 at 7:38
  • @Roy — That won't work. The constant changing of innerHTML will destroy it. – Quentin Commented Aug 31, 2017 at 7:45
  • @NaveedRamzan — How? addEventListener is a method found on elements. A class, in HTML, is just a way to find things in the DOM. – Quentin Commented Aug 31, 2017 at 7:45
  • @Roy — No, I'm wrong. That isn't why it won't work. It won't work because script elements added via innerHTML are not evaluated! – Quentin Commented Aug 31, 2017 at 7:49
Add a ment  | 

5 Answers 5

Reset to default 2

You could change your logic to create the td elements and add the event handler to them at that point. This avoids the issue of deleting the existing HTML within the container, along with all the existing event handlers. Try this:

data.forEach(function(InventSnap) { // loop over all jobs
  var key = InventSnap.key;
  var Items = InventSnap.val();

  var td0 = document.createElement('td');
  td0.id = key;
  td0.classList.add('text-left');
  container.appendChild(td0);

  td0.addEventListener('click', function() {
    console.log('clicked!');
  });

  var a = document.createElement('a');
  a.href = '#';
  a.innerText = key;
  td0.appendChild(a);

  var td1 = document.createElement('td');
  td1.innerText = Items.PartNumber;
  td1.classList.add('text-left');
  container.appendChild(td1);
});

Or the equivalent of this in jQuery would be:

data.forEach(function(inventSnap) {
  var key = inventSnap.key;
  var items = inventSnap.val();

  var $td = $(`<td class="text-left" id="${key}"><a href="#">${key}</a></td>`).on('click', function() {
    console.log('clicked!');
  }).appendTo(container);

  container.append(`<td class="text-left">${items.PartNumber}</td>`);      
});

Create a function to call when all append data is finished !! I tested with add() ,also for more easy to handle ,add one distinct class name to td !!!

var data = [
{key:0,val:"Zero"},
{key:1,val:"One"}
]
Inventorytable(data);
function Inventorytable(data) {
  var container = document.getElementById('iteminfo'); 
  container.innerHTML = '';
  data.forEach(function(InventSnap) { // loop over all jobs
    var key = InventSnap.key;
    var Items = InventSnap.val;
    var jobCard = `
      <td class="text-left first" id="${key}"><a href="#!">${key}</a href></td>
      <td class="text-left" >${Items}</td>
    `;
    container.innerHTML += jobCard;
  });
  add();
}

function add() {
    var container = document.querySelectorAll(".first");
    [].map.call(container, function(elem) {
    elem.addEventListener("click",function(){
      console.log(this.id);
    }, false);
});
}
<table>
<tr id="iteminfo"></tr>
</table>

I would suggest adding a click handler to the #iteminfo as otherwise you would have stall event listeners around when you reorganize your table.

var container = document.getElementById('iteminfo');
container.addEventListener( 'click', ( e ) => {
  const id = e.target.id;
  console.log( id );
} );

var data = [
  { key: 1 },
  { key: 2 },
  { key: 3 },
  { key: 'some-other-key' },
]

function Inventorytable(data) {
  container.innerHTML = '';

  data.forEach(function(InventSnap) { // loop over all jobs
    var key = InventSnap.key;
    var jobCard = `<button id="${key}">${ key }</button>`;

    container.innerHTML += jobCard;
  })
}
Inventorytable( data );
<div id="iteminfo"></div>

Normally: Exactly the same way.

You have the ID in a variable. You can get the element. document.getElementById(key).

… but there's a problem.

container.innerHTML += jobCard;

You keep taking the DOM (with any element listeners bound to it), converting it to HTML (which doesn't carry the event listeners across), appending to it, then converting the HTML back to DOM (giving you a new set of elements without the event listeners).


Rather than destroying the elements each time, you should create them using standard DOM. You can then call addEventListener after creating the element.

data.forEach(function(InventSnap) { // loop over all jobs
  var key = InventSnap.key;
  var Items = InventSnap.val();

  var td = document.createElement("td");
  td.setAttribute("class", "text-left");
  td.setAttribute("id", key);
  td.addEventListener("click", your_event_listener_function);

  var a = document.createElement("a");
  a.setAttribute("href", "");
  a.appendChild(document.createTextNode(key));

  td.appendChild(a);
  container.appendChild(td);

  td = document.createElement("td");
  td.setAttribute("class", "text-left");
  td.appendChild(document.createTextNode(Items.PartNumber));

  container.appendChild(td);

})

You could (either with your original approach or in bination with the above) use delegated events instead:

container.addEventListener("click", delegated_event_listener);

function delegated_event_listener(event) {
    if (test_what_element_was_clicked_on(this)) {
        do_something_with(this.id);
    }
}

You can use event delegation for this:

document.addEventListener('click',function(e) {
    if(e.target && e.target.id === "yourID") {
        //do something
    }
});
发布评论

评论列表(0)

  1. 暂无评论