Detect event on dynamically created elements
Two examples, jQuery and vanilla JavaScript ahead:
jQuery
Use the .on() method with delegated events, which follows this syntax:
$("staticParentSelector").on("eventName", "dynamicChildSelector", handlerFn);
Example:
// Assign event listeners to dynamic child elements
// Will work for either existent elements or inserted in the future
$("#dBlock").on("click", '[type="button"]', (evt) => {
const staticParent = evt.delegateTarget; // This is #dBlock
const dynamicChild = evt.currentTarget; // This is the dynamic child
console.log(`Static Parent ID is: ${staticParent.id}`)
console.log(`Dynamic child ID is: ${dynamicChild.id}`)
});
<!-- STATIC -->
<div id="dBlock">
<!-- ADDED DYNAMICALLY -->
<div id="dCalc">
<button type="button" id="btn1">Add</button>
<button type="button" id="btn2">Subtract</button>
<button type="button" id="btn3">Multiply</button>
<button type="button" id="btn4">Divide</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
JavaScript
The same in vanilla JavaScript can be achieved like the following, with the difference in that JS has no notion of delegateTarget (which is a jQuery property on their proprietary Event object) therefore the slight modification:
// Assign event listeners to dynamic child elements
// Will work for either existent elements or inserted in the future
document.querySelector("#dBlock").addEventListener("click", (evt) => {
const staticParent = evt.currentTarget; // This is #dBlock
const dynamicChild = evt.target.closest('[type="button"]'); // This is the dynamic child
if (!dynamicChild) return; // Do nothing (no designated dynamic child is clicked)
console.log(`Static Parent ID is: ${staticParent.id}`)
console.log(`Dynamic child ID is: ${dynamicChild.id}`)
});
<!-- STATIC -->
<div id="dBlock">
<!-- ADDED DYNAMICALLY -->
<div id="dCalc">
<button type="button" id="btn1">Add</button>
<button type="button" id="btn2">Subtract</button>
<button type="button" id="btn3">Multiply</button>
<button type="button" id="btn4">Divide</button>
</div>
</div>
as you can see neither of the above implementations stick solely on the Event.target
Element per-se, for the reason that if we had i.e. an icon inside the buttons (like: <button id="add" type="button">Add <i class="icon-plus"></i></button>
) and if a click landed on the icon directly, the Event.target
would end up being the icon, not the Button Element - and we might miss to retrieve the needed data, like the specific button ID etc, resulting in a broken app logic.