Why can’t dynamically generated objects trigger a jQuery click event?

What happened

Recently, I was temporarily pulled back to work on a C# .NET project at my company, and I had to set aside the source code scanning task I was working on.

While working on the menu functionality, I encountered the issue I’m going to describe today, and I found it quite interesting, so I decided to document it.

Now, let’s dive straight into the example, and you’ll get a better understanding of the issue I’m talking about.

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<span id="static" class="test">Static</span>
</br>
</br>
<div id="div"></div>

<script>
$('.test').on('click', function () {
	var clickID = $(this).attr('id');
    alert('Clicked element ID is: ' + clickID);
})

var d = $('#div');
var span = document.createElement('span');
span.id = 'dynamic';
span.className = 'test';
span.textContent = 'Dynamic';

d.append(span);
</script>

You can see that there’s a simple .on click event. If an element has the class “test,” clicking it will trigger an alert with its ID.

Additionally, there’s a dynamically generated with the same class. However, something magical happens at this point. Clicking “Static” works perfectly fine, but clicking “Dynamic” doesn’t trigger any response!

Upon further consideration, it appears that the issue may be related to how jQuery handles elements with the “test” class when setting up the event handler with $(‘.test’).on(‘click’, function ()…. It’s likely that jQuery initially scans the page for all elements with the “test” class, possibly using IDs or XPath, and keeps a record of them.

When you click on an element, jQuery checks this list to trigger the event. This explanation helps clarify why dynamically generated elements don’t trigger the event, as they weren’t part of the initial scan.

Solution

It’s actually quite simple.

You can either create the dynamic objects first and then write a global jQuery click event, or you can directly use JavaScript’s click function to bind it to a specific element, like this:

var span = document.createElement('span');
span.id = 'dynamic';
span.className = 'test';
span.textContent = '動態';
span.onclick = function () {
    console.log('動態 <span> 元素被點擊了');
};

Conclusion

Indeed, this can be quite a pitfall! It turns out that jQuery’s events are scanned and bound to the page elements when you define them using .on(‘click’). However, when you think about it, it’s a reasonable approach – it’s like an initialization step.

🧡You can support me by sharing my posts, Thanks a lot

If you got any problem about this post, please feel free to ask me ~

Some Random notes

Leave a Reply

Your email address will not be published. Required fields are marked *