Placing select2 in jquery dataTable does not work


#1

When placing select2 inside the jQuery dataTable, the select2 is not working, when I move it outside the table that is managed by dataTable it works. Here is a example code that shows the issue, in this example same table row is repeated 12 times, and for some odd reason the row number 10 shows up as a select2 managed row but not the others. The issue is validated in latest Chrome and Edge in windows 10 fully updated as of 2019-06-22
Thanks

<!DOCTYPE html>
<html class="no-js" lang="en">

<head>
    <title>T1</title>
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- font awesome stuff -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
            
    <script src="js/jquery.min.js"></script>
    <script src="js/popper.min.js"></script>
    <script src="js/bootstrap.min.js"></script>

    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway:400,800">
    <link rel='stylesheet' href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="css/bootstrap.css">

    <!-- select2 -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>

    <!-- used for sorting -->
    <link rel="stylesheet" href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
    <script type="text/javascript" src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
    <script>
        // jQuery to build a sortable table, use table ID to link it up
        $(document).ready(function() {
            $('#TestTable').dataTable();
        });
        
    </script>
    <script>

        jQuery(document).ready( function () {
            /* this makes the select/option element be customizable. using select2 */
            jQuery(".experience-jquerySelect2-tag").select2( { tags: true } );
        });        
    </script>
    <!-- End -->

    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="0" />

</head>

<body>
    <div class="container">
        <div class="row">
            <!-- for a small display fill 12 columns same for mid size display-->
            <div class="col-sm-12 col-md-12">
                <!-- for this car use mb-2 which means the margin or padding to $spacer * .5-->
                <div class="card mb-2">
                    <!-- for px-1 and py-1 the x - for classes that set both *-left and *-right and 
                        the y - for classes that set both *-top and *-bottom -->
                    <div class="card-body text-left px-1 py-1">
                        <div class="card-text">Test</div>
                        <small class="text-muted">hint hint</small>
                        <div class="p-1 mb-0 bg-warning" style="height: 10px;">&nbsp;</div>
                        <div style="overflow-x:auto;">
                            <!-- table-sm for compact table, table-striped for odd,even coloring -->
                            <table class="table-sm table-striped table-condensed" id="TestTable">
                                <thead>
                                    <tr class="small">
                                        <th scope="col">Drop Down</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td valign="middle" align="left" class="small text-nowrap">
                                           <span class="form-group">
                                                <select class="form-control experience-jquerySelect2-tag" id="IDexperience" name="experience" required>
                                                <option value="Test1">Test 1</option>
                                                <option value="Test2">Test 2</option>
                                                <option value="Test3">Test 3</option>
                                                </select>
                                            </span>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
        

</body>

</html>

#2

Yes, the DataTables.net widget does not play nicely with Select2 out of the box. This is because the DataTables widget renders the rows of the table dynamically (for pagination, searching/filtering, etc.), and since you’ve only called the.select2() initializer once, it will only initialize any matching <select>s that exist in the DOM at that point in time (in your case, when the page initially loads).

So you need to arrange to call the .select2() initializer during or after every DataTable redraw. You have a couple of options:

  1. You can attach an event handler to the draw.dt event (or the preDraw.dt event to run some code when the table has been (re-)drawn (or is about to be—using preDraw.dt might prevent some unnecessary browser reflows since the Select2s would be initialized and in the DOM before the DataTable is redrawn, rather than after it is rendered to the page).
  2. You can use the drawCallback configuration option to specify a function that should be executed every time the table is redrawn. (There are also preDrawCallback and rowCallback callback options, which might give you more control, since they occur at different points in the overall DataTables rendering cycle.) There isn’t much difference between this option and using an event handler (except that there isn’t a rowDraw.dt event), so use whichever method is more comfortable for you.

I recommend you experiment with these options and choose the one that works the best for your application.


#3

Thank you, I am new to jQuery and I tried both drawCallback and perDrawCallback as you mentioned and they are not working, here is the code I used.

<script>
    // jQuery to build a sortable table, use table ID to link it up
    $(document).ready(function() {
        $('#TestTable').dataTable( {
            "preDrawCallback": function( settings ) {
                jQuery(".experience-jquerySelect2-tag").select2( { tags: true } );
                alert( 'DataTables has redrawn the table' );
            }
        } ); 
    } );
    
</script>

#4

Hmm. I took your code and made a quick page out of it, and it seems to work for me using the drawCallback callback (I also tested it with the preDrawCallback and rowCallback options, and they both worked as well). See my code below.

Three (important*) things are different from what you did:

  1. I gave each <select> a unique id attribute value. This is an HTML requirement (each ID attribute value on the page must be unique), and it seems that Select2 enforces this.
  2. I included all of the initialization code in a single $(document).ready() callback.
  3. Since I’m initializing the Select2’s in the DataTable drawCallback when the DataTable is drawn (including when it is initially drawn), there’s no need to separately call the Select2 initializer after initializing the DataTable.

(*There are some “unimportant” differences I made in the HTML and the DataTable and Select2 initializers just to make things easier to test.)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Select2 + DataTables</title>
  <link rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/css/jquery.dataTables.min.css">
  <link rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.min.css">
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/js/jquery.dataTables.min.js"></script>
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js"></script>
  <script>
    $(document).ready(function () {
      $('#TestTable').dataTable({
        pageLength: 5, 
        ordering: false, 
        drawCallback: function(dt) {
          console.log("draw() callback; initializing Select2's.");
          $('.experience-jquerySelect2-tag').select2({tags: true, width: "6em"});
        }
      });
    });
  </script>
</head>

<body>
  <table class="table-sm table-striped table-condensed" id="TestTable">
    <thead>
      <tr class="small">
        <th scope="col">Drop Down</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience1" name="experience" required>
              <option value="Test1">Test 1</option>
              <option value="Test2">Test 2</option>
              <option value="Test3">Test 3</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience2" name="experience" required>
              <option value="Test1">Test 2</option>
              <option value="Test2">Test 3</option>
              <option value="Test3">Test 4</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience3" name="experience" required>
              <option value="Test1">Test 3</option>
              <option value="Test2">Test 4</option>
              <option value="Test3">Test 5</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience4" name="experience" required>
              <option value="Test1">Test 4</option>
              <option value="Test2">Test 5</option>
              <option value="Test3">Test 6</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience5" name="experience" required>
              <option value="Test1">Test 5</option>
              <option value="Test2">Test 6</option>
              <option value="Test3">Test 7</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience6" name="experience" required>
              <option value="Test1">Test 6</option>
              <option value="Test2">Test 7</option>
              <option value="Test3">Test 8</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience7" name="experience" required>
              <option value="Test1">Test 7</option>
              <option value="Test2">Test 8</option>
              <option value="Test3">Test 9</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience8" name="experience" required>
              <option value="Test1">Test 8</option>
              <option value="Test2">Test 9</option>
              <option value="Test3">Test 10</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience9" name="experience" required>
              <option value="Test1">Test 9</option>
              <option value="Test2">Test 10</option>
              <option value="Test3">Test 11</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience10" name="experience" required>
              <option value="Test1">Test 10</option>
              <option value="Test2">Test 11</option>
              <option value="Test3">Test 12</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience11" name="experience" required>
              <option value="Test1">Test 11</option>
              <option value="Test2">Test 12</option>
              <option value="Test3">Test 13</option>
            </select>
          </span>
        </td>
      </tr>
      <tr>
        <td valign="middle" align="left" class="small text-nowrap">
          <span class="form-group">
            <select class="form-control experience-jquerySelect2-tag"
              id="IDexperience12" name="experience" required>
              <option value="Test1">Test 12</option>
              <option value="Test2">Test 13</option>
              <option value="Test3">Test 14</option>
            </select>
          </span>
        </td>
      </tr>
    </tbody>
  </table>

</html>

#5

Thank you John for including sample code.


#6

You’re welcome, and good luck with your project. BTW, are you located in Atlanta? I live in Conyers. Small world, I guess :smile:


#7

small world indeed John. Can you also take a look at this issue I am having with DataTable, I did not see it related to this forum.to post here, it is on stackoverflow with topic [jQuery DataTable how to rebind DataTable when the table is auto refreshed by background process]

thanks
Alex


#8

Can you give me the url of the Stack Overflow post? Searching for the title you gave didn’t return an exact match, and I want to make sure I answer the right question.


#9

Hi John, I found the issue and fixed it, the issue was that I was looking at ajax operation and the jQuery load() as synchronous operation and were calling them in that manner once I realized that they were Async and they have call backs I moved my dataTable there and all worked, I also had some confusion on DataTabe and dataTable which I figured out and fixed.

Thanks for getting back to me and I do live in Buford GA. :wink:


#10

Hey Alex. That’s great. I’m glad you figured it out.

Good luck with your project!