yusufshakeel yusufshakeel - 2 months ago 8
HTML Question

Add event listener and get value on click using plain JavaScript on dynamically generated element

I am trying to console.log the value of data-number attribute of

<span>
on click event using JavaScript. Multiple spans are dynamically created during the execution of the code on the client side and each of them have a class "dynamic-span".

Sample:

<span class="dynamic-span" data-number="1">This is a dynamic span</span>


So when the above span is clicked, number "1" will be console logged.

I am able to log the number using jQuery.

$("body").on("click", ".dynamic-span", function (e) {
e.preventDefault();
var number = $(this).data("number");
console.log(number);
});


I want to achieve the same result using plain JavaScript.

I am targeting the span using the "dynamic-span" class.

var elems = document.getElementsByClassName("dynamic-span");


So, I am able to get the spans using the ClassName. But I am getting HTMLCollection and not an Array and the for loop is not working.

Code:

var
elems = document.getElementsByClassName("dynamic-span"),
i;

for (i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", function (e) {
console.log(this.getAttribute("data-number"));
});
}


I have also checked the following StackOverflow question
Javascript click event listener on class
but no success.

The following reference
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName
suggests the Element.getElementsByClassName() method returns a live HTMLCollection.

Kindly suggest a way to accomplish the above task.

Answer

hopefully this should do it for you:

document.body.onclick = function (e) {
    //get event object (window.event for IE compatibility)
    e = window.event || e;
    //get target dom object reference
    var targetDomObject = e.target || e.srcElement;

    //extra checks to make sure object exists and contains the class of interest
    if ((targetDomObject) && (targetDomObject.classList) && (targetDomObject.classList.contains("dynamic-span"))) {
        var number = targetDomObject.getAttribute("data-number");
        console.log(number);
    }
}

This makes use of bubbling. Whenever an event fires it will move up through all the objects parents until it is marked as handled or there are no more parents. So by attaching to the body's click event it will catch all unhandled click events on the page. The top of the method gets a reference to the event information then it pulls the initial target object from the event. Then all you need to do is see if the object is the object you want to handle and handle it.

Here is a jsfiddle of the code: https://jsfiddle.net/t4jqtLas/

Comments