Select2 dosen't work when I append it using JavaScript function

Hi there! I am trying to make a sales page where user can select products in multiple rows so the select3 in rows which are present when page load works fine but whenever I try to add a new row which has a select2 dropdown doesn’t display a search box. you can see the screenshot below:

and this is my code to insert a new row:

   $(document).on('click', '#add_row', function(){
   count++;
   $('#total_item').val(count);
  var html_code = '';
  html_code += '<tr id="row_id_'+count+'">';
  html_code += '<td><span id="sr_no">'+count+'</span></td>';
  html_code += '<td data-select2-id="'+(count * 50)+'">'+
                  '<div class="form-group">'+
                    '<select class="form-control select2" style="width: 100%;" id="product-name'+count+'" name="product_name[]">'+
                      '<option selected="selected" disabled>Select Product</option>'+
                      <?php foreach($rows as $row){ ?>
                        '<option value="<?php echo($row["product_id"]); ?>"><?php echo($row["product_id"]); ?> | <?php echo($row["product_name"]); ?></option>'+
                      <?php } ?>
                    '</select>'+
                  '</div>'+
                '</td>';
  html_code += '<td> <input type="text" name="rate[]" id="rate1"  class="form-control"> </td>';
  html_code += '<td> <input type="number" name="qty[]" id="qty1" min="1" class="form-control"> </td>';
  html_code += '<td> <input type="text" name="amount[]" id="amount1" class="form-control"> </td>';
  html_code += '<td> <input type="text" name="disc[]" id="disc1" value="0" class="form-control"> </td>';
  html_code += '<td> <input type="text" name="total[]" id="total1" class="form-control"> </td>';
  html_code += '<td> <div class="btn-group btn-group-sm"> <button type="button" onclick="removeRow()" class="btn btn-danger"><i class="fas fa-trash"></i></button> </div> </td>';

  $('#items-list').append(html_code);

});
  });

and this is how I am initializing select2:

$('.select2').select2()

Please let me know what is the right way to do that. Thanks in advance!

Every time you add a new row, you must initialize the Select2 in that row. When you call $('.select2').select2() after page load, that only initializes the Select2s that exist in the HTML page at that time. Any other Select2’s you add after that must be initialized individually. I would recommend you give each new row’s <select> a unique id attribute so you can target just that specific <select> in your $.select2() call; otherwise you will re-initialize all of the Select2’s on the page every time to add a new row, and that will reset any selections in any of the previous Select2s.

(Also, I think your post is missing some HTML; for instance, I don’t see the <select> element you’re adding to each row; I only see the PHP code to generate the <option> elements. If you will put your inside triple-backticks, like this:
```
your code goes here…
```
it will preserve line breaks and indents and make your code easier to read.)

2 Likes

Sorry I didn’t reviewed my code. Please take a look at this again and also how can I initialize the Select2 in newly inserted row?

Just add the following below this line:

$('#items-list').append(html_code);
/* Add the line below to your code: */
$('#' + product-name' + count, '#items-list').select2();

The new line of code finds the new <select> element you just appended and calls the .select2() initialization method on it.

4 Likes

Thank you sir! You saved my life :smiley:

Great, Explanation buddy. U saved my day.

@John30013 can you please have a look into below script.
html input:

Adding below line behaves abnormal and it does not allow to change option
// $(’#isic4select’).html("");
$.ajax({
url: config.routes.isic4catwactivity,
type: “POST”,
dataType: “json”,
async: “false”,
data: { ‘id’: isic4_main_id },
headers: { ‘X-CSRF-TOKEN’: $(‘meta[name=“csrf-token”]’).attr(‘content’) },

        success: function(data) {

            if (data.status) {                    
                var options = '<option>'+isic4_main_val+'</option>';

                $(data.lists).each(function(inx, val) {

                    if(val.activities.length){
                        options +='<optgroup id="'+val.id+'" label="'+val.category_name+'">';

                        $(val.activities).each(function(index, activity) {
                            options +='<option value="'+activity.id+'">'+activity.activity_name+' - '+activity.activity_code+'</option>';

                        });

                        options +='</optgroup>';

                    }
                
                });
            }

            if(options != "")
                $("#isic4select").append(options);                

        }

    });

Note: My requirement is to remove all the options and populate them dynamically

Hello, 
This is my table structure: 
<table id="tbldrug" class="table table-bordered">

                                <thead>

                                    <tr class="headings" bgcolor="#F5F7FA">

                                        <th>S/No.</th>

                                        <th>Drugs</th>

                                        <th>Available Quantity</th>

                                        <th>Quantity</th>

                                    </tr>

                                </thead>

                                <tbody>

                                    <tr class="even pointer">

                                        <td class=" ">1.</td>                                                      

                                        <td>

                                            <select name="drug[0]" id="drug[0]" class="select2" onchange="show_available_quantity(this.id);" required>

                                                <option value="">None</option>

                                                    @foreach($drugs as $a => $drug)

                                                        <option value="{!!$drug->id!!}">{{$drug->name}}</option>  

                                                    @endforeach

                                             </select>                      

                                        </td>

                                        <td class=" ">

                                            <span name="available_quantity[0]" id="available_quantity[0]"></span>

                                        </td>

                                        <td class=" ">

                                            <input type="text" name="quantity[0]" id="quantity[0]" onblur="quantityCheck(this.id)" required>

                                        </td>
                                    </tr>
                                    <tr class="even pointer">

                                        <td class=" " colspan="6">                                          

                                            <button name="add_drug" id="add_drug" type="button" class="btn btn-info" onclick="add_drugs();" > <i class="ace-icon fa fa-plus"> Add</i></button>                                          

                                            <button name="delete_drug" id="delete_drug" type="button" class="btn btn-danger" onclick="delete_drugs();"> <i class="ace-icon fa fa-minus"> Remove</i></button>

                                        </td>

                                    </tr>                                            

                                </tbody>

                            </table>

This is the script I use to add new rows, which also adds a select, however, the select2 is not initialized on the new select, I have tried the solution above, but it still did not work.

function add_drugs() {

                var tbl = document.getElementById('tbldrug');

                var numberOfRows = tbl.rows.length;

                numberOfRows = numberOfRows - 1; // Number of rows already used up in the table object during design after the row to be created.

                var index = numberOfRows - 1;

                var index1 = index + 1;

                var index_displayed = index1 + ".";

                var row = tbl.insertRow(numberOfRows);

                row.style.backgroundColor = '#FFFFFF';

                var cell_serialnumber = row.insertCell(0);

                cell_serialnumber.align = 'left';

                var textNode = document.createTextNode(index_displayed);

                cell_serialnumber.appendChild(textNode);

                var cell_products = row.insertCell(1);

                cell_products.align = 'left';

                var cloneproducts = document.getElementById('drug[0]').cloneNode(true);

                cloneproducts.name = 'drug[' + index + ']';

                cloneproducts.id = 'drug[' + index + ']';

                cloneproducts.className='select2';

                cloneproducts.selectedIndex = "Select Drug";

                cloneproducts.value = "";

                cell_products.appendChild(cloneproducts);

                $('#drug[' + index + ']','#tbl').select2();

               

                var cell_product_volume = row.insertCell(2);

                cell_product_volume.align = 'left';

                var cloneproduct_volume = document.getElementById('available_quantity[0]').cloneNode(true);

                cloneproduct_volume.name = 'available_quantity[' + index + ']';

                cloneproduct_volume.id = 'available_quantity[' + index + ']';

                cloneproduct_volume.innerHTML = '';

                cell_product_volume.appendChild(cloneproduct_volume);

                var cell_product_quantity = row.insertCell(3);

                cell_product_quantity.align = 'left';

                var cloneproduct_quantity = document.getElementById('quantity[0]').cloneNode(true);

                cloneproduct_quantity.name = 'quantity[' + index + ']';

                cloneproduct_quantity.id = 'quantity[' + index + ']';

                cloneproduct_quantity.value = '';

                cell_product_quantity.appendChild(cloneproduct_quantity);

                document.getElementById("hdnnumberof_productsallocated_toastate").value = index;

               

            }

I use $('.select2').select2() to initialize it on page load.

This is the screenshot of my UI, the first row working and subsequent not working.

Kindly help me out.

@John30013 @khasman Kindly help me out.

Your response has helped me. Thank you very much!