Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize select2 dynamically

I insert rows of concepts (with select and input text elements) in my DOM through AJAX. And I want to initialice those select to select2: but I don't know the proper way to do that.

  • I should write the javascript in each row? (Insert html and JS through AJAX)

I get this in each AJAX request:

<select id="concept0"> 
    <option value="Test"> Test </option>
    <option value="Test2"> Test 2 </option>    
</select>
<script> $("#concept0").select2(); </script>

But I think is a wrong idea to return the javascript with the HTML in my AJAX response. There are other alternative?

Thanks and sorry if my question is a little stupid...

like image 589
chemrailM Avatar asked Oct 07 '15 04:10

chemrailM


2 Answers

I would construct the flow like this :

  • Group the partials selects to reduce the number of Ajax requests
  • Add markers to the partial HTML with 'data-'
  • Retrieve partial html with AJAX GET;
  • Initialize elements;
  • [Optionally] Detach the target parent element - performance reasons;
  • Append elements to the target;
  • [Optionally] Reattach the target element;
  • Initialize the widgets.

I've made a simulation here : http://jsbin.com/jotitu/edit?js,output

Bellow is a little explanation:

So lets say you have the following HTML:

<div id="concept-table-container">
 <table>
   <tr>
     <th>
        No.
     </th>
     <th>
        Name.
     </th>
     <th>
        Option.
     </th>
   </tr>
   <tr>
     <td>1</td>
     <td>abc</td>
     <td></td>
   </tr>
   <tr>
     <td>2</td>
     <td>dce</td>
     <td></td>
   </tr>
   <tr>
     <td>3</td>
     <td>fgh</td>
     <td></td>
   </tr>
 </table>
</div>

Group the partials selects to reduce the number of Ajax requests and add markers to the partial HTML with 'data-'

If you can group and write your partial HTML like this you won't need to do to an Ajax request for each row. You can chose to limit them also, but that requires a bit more programming for "pagination".

<select data-widget="select2" data-row-idx="0"> 
    <option value="Test"> Test </option>
    <option value="Test2"> Test 2 </option>    
</select>
<select data-widget="select2" data-row-idx="1"> 
    <option value="Test"> Test </option>
    <option value="Test2"> Test 2 </option>    
</select>
<select data-widget="select2" data-row-idx="2"> 
    <option value="Test"> Test </option>
    <option value="Test2"> Test 2 </option>    
</select>

Retrieve partial html with AJAX GET

I won't get here into the details, it's enough to say that :

$.get(conceptPartialUrl, successCallback);

Initialize elements;

var successCallback = function(data){
  var $fragmentEl = initEls(data);
  // Optionally before appending the selects detach the container;
  appendElements($fragmentEl, $containerEl);
  // Initialize the widgets.
  initSelect2Widgets();
};


var initEls = function(data){
  // Create DOM elements - JQuery Way
  var $fragmentEl = $(data);
  // Return the reference
  return $fragmentEl;
};

Append elements to the target;

var appendElements = function($fragmentEl, $containerEl){
   var $rows = $containerEl.find('tr');
   $fragmentEl.each(function(){     
      var $el = $(this);


      // some matching - you 
      var idx = $el.data('row-idx');

      // that plus 1 is to skip the header        
      // find the row         
      var $row = $rows.eq(idx+1);         
      // find the cell, empty it and append the element  
      $row .find('td').last().text('').append($el);
   });
};

Initialize the widgets

var initSelect2Widgets = function(){
  $containerEl.find('[data-widget="select2"]').select2();
};
like image 87
Tiberiu C. Avatar answered Sep 25 '22 16:09

Tiberiu C.


I have got another way around for this :

As you said in your comment that you send a counter in each ajax request (I hope that you are using that counter to generate id of select), you can store that in some element or js variable before ajax request. So that at every ajax request you have that unique value of counter.

Than you can initialize you select2 using :

$(document).ajaxComplete(function() {
    $(document).find('your-unique-counter-select-id').select2();
});
like image 27
Harsh Makani Avatar answered Sep 26 '22 16:09

Harsh Makani