Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialising select2 created dynamically

I have a select2 drop-down for which I provide a matcher function. It is initialised like this on initial page load:

jQuery(document).ready(function() {
    jQuery(".my_select2").select2({
        matcher: function(term, text) {...}
    });
});

That works find on initial page load.

Now, I have additional drop-downs (select elements created dynamically (pulled in via AJAX, i.e. jQuery(match).load(url). These additional drop-downs do not get intialised as select2 widgets, which is understandable, even though they match the original select2 selector.

So, how can I tell jQuery to treat these dynamically-created select elements as select2 items that need to be initialised? Can I set some kind of "watch" on matching elements so the select2 initialisation kicks in every time a matching element gets added to the page?

I recall live() being introduced in jQuery some time ago, that supported matching elements before they are created, if I understood it correctly. I never used that feature, and it now appears deprecated. But it does feel like the kind of thing I am looking for.

This is for a WordPress plugin, which uses jQuery v1.11.2 at present.

like image 487
Jason Avatar asked Apr 30 '15 15:04

Jason


People also ask

How do I create a Select2 dynamically?

Select2 jQuery plugin is easy to add on the <select > element. Need to call the select2() method on the selector to initialize. If you adding select2 on a class or select element and when you add an element dynamically then select2 is not initialized on that element.

How to initialize Select2 in jQuery?

Select2 will register itself as a jQuery function if you use any of the distribution builds, so you can call . select2() on any jQuery selector where you would like to initialize Select2. // In your Javascript (external . js resource or <script> tag) $(document).

How to add option in Select2 using jQuery?

New options can be added to a Select2 control programmatically by creating a new Javascript Option object and appending it to the control: var data = { id: 1, text: 'Barn owl' }; var newOption = new Option(data. text, data.id, false, false); $('#mySelect2'). append(newOption).

How to add Select2?

In order to use Select2, you must include the compiled JavaScript and CSS files on your website. There are multiple options for including these pre-compiled files, also known as a distribution, in your website or application.


4 Answers

you can try with DOMNodeInserted and look for select or the class you're assigning them

Demo

$('body').on('DOMNodeInserted', 'select', function () {
    $(this).select2();
});

Update

DOMNodeInserted

Deprecated This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Avoid using it and update existing code if possible;

The suggested method would be something like this with MutationObserver

$(function() {
  $("button").on("click", function() {
    $("#dynamic-container").append($("<select><option>test</option><select/>"));
  });

  // select the target node
  var target = document.getElementById('dynamic-container');

  if (target) {
    // create an observer instance
    var observer = new MutationObserver(function(mutations) {
      //loop through the detected mutations(added controls)
      mutations.forEach(function(mutation) {
      //addedNodes contains all detected new controls
        if (mutation && mutation.addedNodes) {
          mutation.addedNodes.forEach(function(elm) {
          //only apply select2 to select elements
            if (elm && elm.nodeName === "SELECT") {
              $(elm).select2();
            }
          });
        }
      });
    }); 
    
    // pass in the target node, as well as the observer options
    observer.observe(target, {
      childList: true
    });

    // later, you can stop observing
    //observer.disconnect();
  }
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>


<button>Add new select</button>
  <div id="dynamic-container">

  </div>
like image 128
Juan Avatar answered Oct 02 '22 16:10

Juan


I came across a similar situation recently but did it in a very usual way:

$(document).ready(function() {

 //function to initialize select2
  function initializeSelect2(selectElementObj) {
    selectElementObj.select2({
      width: "80%",
      tags: true
    });
  }


 //onload: call the above function 
  $(".select-to-select2").each(function() {
    initializeSelect2($(this));
  });

 //dynamically added selects

  $(".add-new-select").on("click", function() {
    var newSelect = $("<select class='select-to-select2'  multiple><option>option 1</option><option>option 2</option></select>");
    $(".select-container").append(newSelect);
    initializeSelect2(newSelect);
  });


});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.css" rel="stylesheet" />

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js"></script>
<div class="select-container">
  <select class='select-to-select2' multiple>
    <option value='1'>option1</option>
    <option value='2'>option2</option>
  </select>

  <select class='select-to-select2' multiple>
    <option value='1'>option1</option>
    <option value='2'>option2</option>
  </select>

</div>
<div>
  <button class="add-new-select">Add New Select</button>
</div>

In case of the .load function find all the select elements which are to be initialized in the callback of load function and call initializeSelect2 on each of those select elements.

I hope this helps someone who is looking for a simple solution.

like image 29
roshan Avatar answered Oct 04 '22 16:10

roshan


It works for me

<div id="somediv">
    <select class="component">
    ...
    </select>
</div>



<script>
    $(document).on('click', '#addComponent', function () {

        $('#somediv').append(data); //data is my new select
        $('.component:last').select2();
    });
</script>
like image 27
Уляна Різник Avatar answered Oct 02 '22 16:10

Уляна Різник


I have faced the same issue, But after scratching my head for days, I found a solution but its not good if you expect good performance.

So when DOM loaded for first time, whatever select items are loaded will have select2 functionality, For dynamic generated fields select2 functionality wont be available because the select2 scripts are already loaded.

So to make the select2 work, reload the scripts dynamically on click.

function reload(id) {
    $(id).on("click", function () {
        $("head").append($("<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.css' type='text/css' media='screen' />"));
        $.getScript("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js", function () {
            $.getScript("https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js", function () { 
                $('select').select2();
            })
        })
    })
}

What this does is, it adds the select2 functionality to $.

like image 36
mourya venkat Avatar answered Oct 01 '22 16:10

mourya venkat