Search code examples
jqueryjquery-selectors

Datatables - how to retain filter data and reassign them to dropdowns


I'm using Jquery datatables and it has filters in the form of dropdowns. The HTML looks like below.

<table id="example">
   <thead>
     <tr>
       <th>Name</th>
       <th>Position</th>
       <th>Office</th>
       <th>Age</th>
       <th>Start date</th>
       <th>Salary</th>
     </tr>
     <tr>
       <td></td>
       <td><select><option>-Filter-</option></select></td>
       <td><select><option>-Filter-</option></select></td>
       <td></td>
       <td></td>
       <td></td>
     </tr>
   </thead>
   <tbody>
     <tr>
       <td>Tiger Nixon</td>
       <td>System Architect</td>
       <td>Edinburgh</td>
       <td>61</td>
       <td>2011-04-25</td>
       <td>$320,800</td>
     </tr>
     <tr>
       <td>Tiger Nixon</td>
       <td>System Architect</td>
       <td>Edinburgh</td>
       <td>61</td>
       <td>2011-04-25</td>
       <td>$320,800</td>
     </tr>
   </tbody>
  </table>

Filter dropdown can be in any column as this is used in many places with different datasets. Therefore, I've made it dynamic with the use of Datatable's provided method and managed to get as far as locating the <td> element with the filter dropdown.

var filterColumn = $("#example thead tr:eq(1) td:eq(" + i + ") select");

In the code snippet above, i being the column number which comes from the overarching function and successfully get assigned inside td:eq, however, my Jquery selector won't return the dropdown inside the table cell, instead returns Jquery Object as below.

enter image description here

Any help is much appreciated to fix the selector.

JS bin - https://jsbin.com/badopohino/edit?html,js,output

Thanks.

$('#example').DataTable({
  orderCellsTop: true,
  stateSave: true,
  initComplete: function() {
    this.api()
      .columns([1, 2])
      .every(function() {
        var column = this;
        var select = $('<select class="form-control form-control--filter"><option value=""> -- Filter -- </option></select>')
          .appendTo($('thead tr:eq(1) td:eq(' + this.index() + ')'))
          .on('change', function() {
            var val = $.fn.dataTable.util.escapeRegex(
              $(this).val()
            );
            column
              .search(val ? '^' + val + '$' : '', true, false)
              .draw();
          });

        column.data().unique().sort().each(function(d, j) {
          if (!d == '') {
            select.append('<option value="' + d + '">' + d + '</option>');
          }
        });
      });
  },
  stateLoadParams: function(settings, data) {
    for (i = 0; i < data.columns["length"]; i++) {
      var col_search_val = data.columns[i].search.search;

      if (col_search_val != "") {
        var filterColumn = $("#example thead tr:eq(1) td:eq(" + i + ") select");
        console.log(filterColumn, i);
      }
    }
  }


});

var abc = $("#example thead tr:eq(1) td:eq(1) select");

//console.log(abc);
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>
  <!DOCTYPE html>
  <html>

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="//cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css">
    <title>JS Bin</title>
  </head>

  <body>
    <table id="example" class="table table-striped">
      <thead>
        <tr>
          <th>Name</th>
          <th>Position</th>
          <th>Office</th>
          <th>Age</th>
          <th>Start date</th>
          <th>Salary</th>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Tiger Nixon</td>
          <td>System Architect</td>
          <td>Edinburgh</td>
          <td>61</td>
          <td>2011-04-25</td>
          <td>$320,800</td>
        </tr>
        <tr>
          <td>Garrett Winters</td>
          <td>Accountant</td>
          <td>Tokyo</td>
          <td>63</td>
          <td>2011-07-25</td>
          <td>$170,750</td>
        </tr>
        <tr>
          <td>Ashton Cox</td>
          <td>Junior Technical Author</td>
          <td>San Francisco</td>
          <td>66</td>
          <td>2009-01-12</td>
          <td>$86,000</td>
        </tr>
        <tr>
          <td>Cedric Kelly</td>
          <td>Senior Javascript Developer</td>
          <td>Edinburgh</td>
          <td>22</td>
          <td>2012-03-29</td>
          <td>$433,060</td>
        </tr>
        <tr>
          <td>Airi Satou</td>
          <td>Accountant</td>
          <td>Tokyo</td>
          <td>33</td>
          <td>2008-11-28</td>
          <td>$162,700</td>
        </tr>
        <tr>
          <td>Brielle Williamson</td>
          <td>Integration Specialist</td>
          <td>New York</td>
          <td>61</td>
          <td>2012-12-02</td>
          <td>$372,000</td>
        </tr>
      </tbody>
    </table>
    <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
    <script src="//cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>

  </body>

  </html>
</body>

</html>


Solution

  • Managed to solve this by saving the filter data within the stateLoadParms method and then looping through them in the initComplete method and setting the selected value to the dropdown. Haven't tested the code below but what I was missing was that the Jquery selector couldn't find the dropdown elements inside table cells as they are added to the DOM later, as pointed out above by @Barmar.

    var filterData = [];
    $('#example').DataTable({
      orderCellsTop: true,
      stateSave: true,
      initComplete: function() {
        this.api()
          .columns([1, 2])
          .every(function(index) {
            var column = this;
            var select = $('<select class="form-control form-control--filter"><option value=""> -- Filter -- </option></select>')
              .appendTo($('thead tr:eq(1) td:eq(' + this.index() + ')'))
              .on('change', function() {
                var val = $.fn.dataTable.util.escapeRegex(
                  $(this).val()
                );
                column
                  .search(val ? '^' + val + '$' : '', true, false)
                  .draw();
              });
    
            var option;
            column.data().unique().sort().each(function(d, j) {
              if (!d == '') {
                option = $('<option value="' + d + '">' + d + '</option>');
                if (d == filterData[index]) {
                  option.prop('selected', true);
                }
                select.append(option);
              }
            });
    
          });
      },
      stateLoadParams: function(settings, data) {
        data.columns.forEach(function(col, i) {
          filterData.push(col.search.search);
        });
      }
    });
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    
    <body>
      <!DOCTYPE html>
      <html>
    
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="//cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css">
        <title>JS Bin</title>
      </head>
    
      <body>
        <table id="example" class="table table-striped">
          <thead>
            <tr>
              <th>Name</th>
              <th>Position</th>
              <th>Office</th>
              <th>Age</th>
              <th>Start date</th>
              <th>Salary</th>
            </tr>
            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Tiger Nixon</td>
              <td>System Architect</td>
              <td>Edinburgh</td>
              <td>61</td>
              <td>2011-04-25</td>
              <td>$320,800</td>
            </tr>
            <tr>
              <td>Garrett Winters</td>
              <td>Accountant</td>
              <td>Tokyo</td>
              <td>63</td>
              <td>2011-07-25</td>
              <td>$170,750</td>
            </tr>
            <tr>
              <td>Ashton Cox</td>
              <td>Junior Technical Author</td>
              <td>San Francisco</td>
              <td>66</td>
              <td>2009-01-12</td>
              <td>$86,000</td>
            </tr>
            <tr>
              <td>Cedric Kelly</td>
              <td>Senior Javascript Developer</td>
              <td>Edinburgh</td>
              <td>22</td>
              <td>2012-03-29</td>
              <td>$433,060</td>
            </tr>
            <tr>
              <td>Airi Satou</td>
              <td>Accountant</td>
              <td>Tokyo</td>
              <td>33</td>
              <td>2008-11-28</td>
              <td>$162,700</td>
            </tr>
            <tr>
              <td>Brielle Williamson</td>
              <td>Integration Specialist</td>
              <td>New York</td>
              <td>61</td>
              <td>2012-12-02</td>
              <td>$372,000</td>
            </tr>
          </tbody>
        </table>
        <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
        <script src="//cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
    
      </body>
    
      </html>
    </body>
    
    </html>