Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attach javascript/jquery event on dynamically created elements

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.

Example adding the select2 plugin to wordpress. Clicking quick edit adds new fields

New selects don't load properly. and there is no dropdown when clicking on them.

Clicking once on the select and then below it will load the select2 overlay wrong

like image 921
Bryan Willis Avatar asked Jun 07 '14 07:06

Bryan Willis


2 Answers

Solution:

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.

like image 61
Sanjeev Avatar answered Sep 29 '22 19:09

Sanjeev


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..

like image 38
razahassank Avatar answered Sep 29 '22 18:09

razahassank