I've seen a lot of different questions similar to this, but all of them generally targeted a specific selector. Please let me know if there is a duplicate somewhere and I've missed it.
Take this scenario:
You want to build a jquery plugin for a wordpress, drupal, or basically any site that uses third party functionality. Since you don't know ahead of time every specific event and selector you will need to target how would you add jquery/javascript functionality to elements that are created dynamically. Plus you don't know how the element is created (callback using ajax/php/etc).
Example:
I recently tried adding select2 or selectize to my entire site. Unfortunately, since I can't determine ahead of time when select elements (from other plugins/modules) will be added, I can't ensure that the select jquery will work on newly created selects.
Select2
This is the normal way but doesn't work on dynamically created or cloned selects:
<script type='text/javascript'>
jQuery(document).ready(function($) {
$("select").select2();
});
</script>
If I knew all the events that added these selects I could simply do the following:
$( ".some_button_that_creates_new_selects" ).on( "click", function() {
jQuery("select").select2();
});
});
However, since I don't know all the selectors of dynamic selects ahead of time (since many are added by 3rd party plugins), select2 will not work on new selects. So the above would only work on a per case senerio.
I need to find a way to traverse through the dom tree and recognize when new selects are created.
I tried targeting several events with .on but it didn't work well at all.
I read that the javascript document.getElementsByTagName
recognizes changes in the dom and are reflected in the collection. I also looked into querySelectorAll
, but not sure exactly how it works.
I also tried messing with the MutationObserver
and checking if the .addednodes.length
of select tags changed, but I didn't really get anywhere.
UPDATE
After doing some testing I realized that the problem might lie within the select2 plugin itself. Select2 loads dynamic selects but doesnt get the positioning. Chrome eventually throws typeerros : cannot read property 'find' of null, cannot read property 'hasclass' of null.
I am going to answer your base question "Attach javscript/jquery event on dynamically created elements".
For adding event on dynamically created elements you have to take advantage or Event Delegation, when a event trigger on an element it propagates.
So if you attach event handler on a root element( it can be body or any parent element which is present when you are attaching this event)
$("body").on("click","elementSelector", function(){
});
Now this will capture event from dynamically created elements as well.
The easiest solution is to create a function in javascript which will be called everytime when you add any control dynamically on the page and in that function you can placed the check so event will be registered only on new components. e.g.
function registerEvents()
{
//Get all the select events from the page and register events only on those controls which are new ..
$("select").each(function() {
if (!$(this).hasClass("registeredEvent")) {
$(this).addClass("registeredEvent");
$(this).select2();
}
});
}
Same results can be achieved through different approaches..
Also check .live event in jquery .. it register events automatically when the new element is added with the same tag or class..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With