Introduction
When you call addEventListener
, only the tags that exist receive the event. Future tags that do not exist yet will not have that event. You need to somehow guarantee that future elements also have the event. There are multiple ways that you can use to achieve this.
onclick
One very simple way to guarantee that your click
event will be handled is to specify an onclick
attribute to the tag, like
onclick="yourfunction
Example:
function foo(element) {
alert([...element.parentNode.children].indexOf(element));
}
function addDiv() {
let container = document.getElementById("container");
container.innerHTML += `
<p onclick="foo(this);">${container.children.length}</p>
`;
};
<input type="button" onclick="addDiv()" value="Click Here!">
<div id="container">
</div>
Adding event listeners on the fly
It is also possible to somehow mark the items that already have been initialized and subsequently add the event only to items that are not yet initialized and subsequently initialize them.
Example:
function foo(element) {
alert([...element.parentNode.children].indexOf(element));
}
function addDiv() {
let container = document.getElementById("container");
container.innerHTML += `
<p onclick="foo(this);">${container.children.length}</p>
`;
for (let item of document.querySelectorAll(".container > div:not(.initialized)")) {
item.addEventListener("click", () => {
foo(this);
this.classList.add("initialized");
});
}
};
<input type="button" onclick="addDiv()" value="Click Here!">
<div id="container">
</div>
Adding an event listener to an HTML node
You can simply call videoComponent.addEventListener
.
Example:
function foo(element) {
alert([...element.parentNode.children].indexOf(element));
}
function addDiv() {
let container = document.getElementById("container");
let newNode = container.children[0].cloneNode(true);
newNode.innerText = container.children.length;
container.appendChild(newNode);
newNode.addEventListener("click", function() {
foo(this);
});
};
document.getElementById("container").children[0].addEventListener("click", function() {
foo(this);
});
<input type="button" onclick="addDiv()" value="Click Here!">
<div id="container">
<p>0</p>
</div>
Mutation Observer
Courtesy to Mutation Observer for creating new elements
You can use Mutation Observer to detect tag creation and attach events to it. It should be avoided if possible, more often than not you have a simpler solution, but, for the sake of completeness, here's an example taken from the link shared above:
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
$("#foo").live("click",function(e) {
e.preventDefault();
$(this).append($("<div />").html("new div").attr("id","bar"));
});
// define a new observer
var obs = new MutationObserver(function(mutations, observer) {
// look through all mutations that just occured
for(var i=0; i<mutations.length; ++i) {
// look through all added nodes of this mutation
for(var j=0; j<mutations[i].addedNodes.length; ++j) {
// was a child added with ID of 'bar'?
if(mutations[i].addedNodes[j].id == "bar") {
console.log("bar was added!");
}
}
}
});
// have the observer observe foo for changes in children
obs.observe($("#foo").get(0), {
childList: true
});
Event delegation
Last, but not least, as others already mentioned, you can delegate your event to the parent node, but in that case you will need to find out what the originator of the event was, which is the event object's target
field.
Example:
function foo(element) {
alert([...element.parentNode.children].indexOf(element));
}
function addDiv() {
let container = document.getElementById("container");
container.innerHTML += `
<p>${container.children.length}</p>
`;
};
document.getElementById("container").addEventListener("click", function(event) {
foo(event.target);
});
<input type="button" onclick="addDiv()" value="Click Here!">
<div id="container">
</div>