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?
- 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
5 Answers
Reset to default 2You 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
}
});