Search code examples
javascripthtmldatatables

Datatables does not retain the selected filter column values if the value has special characters


I am using cascading datatables. It works fine. It appears, however, that if I select a value under Name or Office, the selected value is not retained in the dropdown menu. However, if I select Postion, it retains the selected value, for example: Director or System Architect.

It is because Columns 1 and 3 have special characters in the column values, which probably explains why it does this. (. - :) etc. Is there a way around this? Users are unable to tell which value was selected from the dropdown menu.Thanks.

https://live.datatables.net/suwopemu/1/edit

$(document).ready(function() {
  var table = $('#example').DataTable({
    responsive: true,
    searching: true
  });

  buildSelect( table );
  table.on( 'draw', function () {
    buildSelect( table );
  } );


});

function buildSelect( table ) {
  var counter = 0;
  table.columns( [0, 1, 2] ).every( function () {
    var column = table.column( this, {search: 'applied'} );
    counter++;
    var select = $('<select><option value=""></option></select>')
    .appendTo( $( '#dropdown' + counter ).empty() )
    .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 ) {
      select.append( '<option value="'+d+'">'+d+'</option>' );
    } );
    
    // The rebuild will clear the exisiting select, so it needs to be repopulated
    var currSearch = column.search();
    if ( currSearch ) {
      select.val( currSearch.substring(1, currSearch.length-1) );
    }
  } );
}
<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>

    <link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
    <script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>

    <meta charset=utf-8 />
    <title>DataTables - JS Bin</title>
  </head>
<div class="searchbox">
<p>Name: <span id="dropdown1">
  </span>
</p>

<p>Postion: <span id="dropdown2">
  </span>
</p>

<p>Office: <span id="dropdown3">
</span>
</p>
  <button type="button" id="test">Clear Filters</button>
</div>
  <table id="example" class="cell-border row-border stripe dataTable no-footer dtr-inline" role="grid" style=" width: 100%; padding-top: 10px;"><thead>
<tr>

<th>&#160;</th>
<th>&#160;</th>
<th>&#160;</th>
<th colspan="3" style=" text-align: center;">Information</th>
</tr>


          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </thead>

        
        <tbody>
          <tr>
            <td>ID.AI</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>61</td>
            <td>2011/04/25</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Garrett -2</td>
            <td>Director</td>
            <td>Edinburgh</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Ashton.1 -2</td>
            <td>Technical Author</td>
            <td>San Francisco</td>
            <td>66</td>
            <td>2009/01/12</td>
            <td>$4,800</td>
          </tr>
          
            
          </tr></tbody></table>
</div>


Solution

  • The problem is column.search() is returning a regex pattern to match. So I simply modified the

    // The rebuild will clear the exisiting select, so it needs to be repopulated
    var currSearch = column.search();
    if ( currSearch ) {
      select.val( currSearch.substring(1, currSearch.length-1) );
    }
    

    section to use regEx and find the value in the unique list

    // The rebuild will clear the exisiting select, so it needs to be repopulated
    var currSearch = column.search();
    if ( currSearch ) {
      select.val( column.data().unique().toArray().find((e) => e.match(new RegExp(currSearch))) );
    }
    

    Here is a working example of this in action

    $(document).ready(function() {
      var table = $('#example').DataTable({
        responsive: true,
        searching: true
      });
    
      buildSelect(table);
      table.on('draw', function() {
        buildSelect(table);
      });
    
    
    });
    
    function buildSelect(table) {
      var counter = 0;
      table.columns([0, 1, 2]).every(function() {
        var column = table.column(this, {
          search: 'applied'
        });
        counter++;
        var select = $('<select><option value=""></option></select>')
          .appendTo($('#dropdown' + counter).empty())
          .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) {
          select.append('<option value="' + d + '">' + d + '</option>');
        });
    
        // The rebuild will clear the exisiting select, so it needs to be repopulated
        var currSearch = column.search();
        if (currSearch) {
          // ** MY CHANGE **
          // Use RegEx to find the selected value from the unique values of the column.
          // This will use the Regular Expression returned from column.search to find the first matching item in column.data().unique
          select.val(column.data().unique().toArray().find((e) => e.match(new RegExp(currSearch))));
        }
      });
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
    <script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
    <div class="searchbox">
      <p>Name: <span id="dropdown1">
        </span>
      </p>
    
      <p>Postion: <span id="dropdown2">
        </span>
      </p>
    
      <p>Office: <span id="dropdown3">
        </span>
      </p>
      <button type="button" id="test">Clear Filters</button>
    </div>
    <table id="example" class="cell-border row-border stripe dataTable no-footer dtr-inline" role="grid" style=" width: 100%; padding-top: 10px;">
      <thead>
        <tr>
    
          <th>&#160;</th>
          <th>&#160;</th>
          <th>&#160;</th>
          <th colspan="3" style=" text-align: center;">Information</th>
        </tr>
    
    
        <tr>
          <th>Name</th>
          <th>Position</th>
          <th>Office</th>
          <th>Age</th>
          <th>Start date</th>
          <th>Salary</th>
        </tr>
      </thead>
    
    
      <tbody>
        <tr>
          <td>ID.AI</td>
          <td>System Architect</td>
          <td>Edinburgh</td>
          <td>61</td>
          <td>2011/04/25</td>
          <td>$3,120</td>
        </tr>
        <tr>
          <td>Garrett -2</td>
          <td>Director</td>
          <td>Edinburgh</td>
          <td>63</td>
          <td>2011/07/25</td>
          <td>$5,300</td>
        </tr>
        <tr>
          <td>Ashton.1 -2</td>
          <td>Technical Author</td>
          <td>San Francisco</td>
          <td>66</td>
          <td>2009/01/12</td>
          <td>$4,800</td>
        </tr>
      </tbody>
    </table>