Sebbo
Sebbo

Reputation: 405

Is it possible to filter a jQuery DataTable by data attribute?

I was wondering if it is at all possible to filter a jQuery DataTable by one of its data attributes instead of the contents of its cells. To dynamically apply a filter to a column, one uses this call:

$table.fnFilter('^(Some value)$', columnIndex, true, false);

This will filter the exact contents of the cell by default using regex. However, assume that my cells are structured this way:

<td data-label="Active"><i class="fa fa-check fa-lg"></i></td>

Or

<td data-label="Active">Active<br /><span class="mute">Some text</span></td>

I would like to be able to have the DataTable filter by the exact content of the attribute data-label instead of the cell contents. Is it a matter of defining the search type when setting up columns on table init? Or is there a way to define to filter by attribute instead of contents?

Upvotes: 7

Views: 19696

Answers (4)

Flavio Sampaio
Flavio Sampaio

Reputation: 11

I am a little late here but I see another solution that simplify this issue: In HTML: Pick a column to filter your data: (I pick 1st column)

<td><div data-filter="filter1" >...</div></td>

In JS:

 $.fn.dataTable.ext.search.push( (settings, data, dataIndex, rowData ) =>{ 
            var row=$(rowData[0]); 
            var filterData = $(rowData[0]).attr('data-filter');
            return filter === 'filter1';
           });

Upvotes: 1

Don Cheadle
Don Cheadle

Reputation: 5576

var detailDT = $("#staging-detail-table").DataTable();

var selectedHeaderId = $(...).click...

$.fn.dataTable.ext.search.push(
       function (settings, searchData, dataIndex, rowData) {

            // This is a global call-back, so check what table is getting sent thru
            // for different search logic.
            // This is triggered any time any table is re-drawn.

            // Detail grid
            if (settings.nTable.id == "staging-detail-table") {
                if (!selectedHeaderId) {
                    // no header was selected. show everything
                    return true;
                } else {
                    var $trDetailDT = $(detailDT.row(dataIndex).node());
                    var headerId = $trDetailDT.data("headerid");

                    return selectedHeaderId == headerId;
                }
            }

            return true; // it wasnot the staging data table. Don't filter/limit.
        }
)

detailDT is a reference to the DataTable I want to filter.

selectedHeaderId is the value I want to filter by - would have been set by some other jQuery user interaction etc. before calling detailDT.draw() which triggers the search.

Key part is calling $(detailDT.row(dataIndex).node()); which uses the callback param dataIndex of the current row. This basically gets the row into a normal jQuery object to get data attributes etc.

Upvotes: 1

Roman86
Roman86

Reputation: 2309

you may also define a per-table custom callback by storing it in "settings" in initComplete callback and then invoking in from instance's "settings" object under common search handler. Here's the code:

$(function(){
  // the common/unified plugin (for all datatables)
  $.fn.DataTable.ext.search.push(
        function(settings, columnsOutput, dataIndex, data, outputIndex) {
          // this = ext.search array (all custom search functions (including this one)
          if (settings._myFilter){
              return settings._myFilter.call(settings, {
                  data: data,
                  dataIndex: dataIndex,
                  outputIndex: outputIndex,
                  columnsOutput: columnsOutput,
                  settings: settings
              });
          } else {
              return true;
          }
      }
      );

  // exact datatable initialization
  var dTable = $("#example").DataTable({
    // some sample data
    data: [{name: "John"}, {name: "Jack"}, {name: "Andy"}],
    columns: [{data: 'name'}],
    // setting our custom function under the initComplete callback
    initComplete: function(settings, json) {
      settings._myFilter = function(info){
        if ($('#jFilter').prop('checked')){
          return (info.data.name.toLowerCase().indexOf('j') >= 0);
        } else {
          return true;
        }
      }
    }
  });
  
  $('#jFilter').on('click', function(){
    dTable.draw(); // redraw will apply all the filters
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.0/js/jquery.dataTables.js"></script>
<link href="https://cdn.datatables.net/1.10.0/css/jquery.dataTables.css" rel="stylesheet"/>

<h2>Click checkbox below to filter by data using a callback</h2>
<label><input id="jFilter" type="checkbox"> J only</label>

<table id="example">
</table>

Upvotes: 3

davidkonrad
davidkonrad

Reputation: 85558

If you want to trigger the filter by code, create a custom filter :

$.fn.dataTable.ext.search.push(
   function(settings, data, dataIndex) {
      var dataLabel = table
          .row(dataIndex)         //get the row to evaluate
          .nodes()                //extract the HTML - node() does not support to$     
          .to$()                  //get as jQuery object 
          .find('td[data-label]') //find column with data-label
          .data('label');         //get the value of data-label
      return dataLabel  == 'Active'; 
   }     
);

demo -> http://jsfiddle.net/x83zm7qq/

If you just want to be able to use data-label as the target of filtering when the user types in the searchbox, you can rename data-label to data-search or data-filter :

<td data-search="Active"><i class="fa fa-check fa-lg"></i></td>

dataTables calls it orthogonal data.

Upvotes: 14

Related Questions