Search code examples
htmljquerydatatablescustom-data-attribute

Filtering a jquery datatable on a TR data-attribute


I have a query that is similar, but not the same as, this question.

The difference is I'm trying to filter by a data attribute on the row rather than the column. The tr element, not the td element. This contains a primary key and I'm trying to remove duplicates. Duplicate rows may differ in actual column data, so I can't do it that way. The key is a combination of three numeric fields separated by underscores.

<tr data-primarykey="12345678_12_34"><td>... 

Then, inside a javascript function called on page load...

  var rows = [];
  $.fn.DataTable.ext.search.push(
    function( settings, data, dataIndex, rowObj, counter ) {
      if(counter === 0) rows = [];

      // I want rowkey to be the data-primarykey attribute of the tr element
      var rowkey = table.row(dataIndex).data('primarykey');

      // If we've seen the row before (already in the array), filter it out.
      // Otherwise, return true and add it to the array
      if ($.inArray(rowkey,rows) > -1) return false;
      else {
        rows.push(rowkey);
        return true;
      }
    }
  );

I suspect that part of the problem is that table object not being defined anywhere. This filter is applying to multiple tables, so it would need to be whatever table is currently being filtered, if possible. Each table has a unique id, but share a class attribute.

Update 2016/12/12

I have made some progress with a version that uses the actual data attributes. This version has a working table DataTable object and I think correctly gets the row and converts it to jquery. However, attempting to get the data-attribute results in undefined.

$.fn.DataTable.ext.search.push(
    function( settings, data, dataIndex, rowObj, counter ) {
      if(counter === 0) rowkeys = [];

      // I want rowkey to be the data-primarykey attribute of the tr element
      var tableID = $(settings.nTable).attr("id");
      var table = $('#'.tableID).DataTable(); // Correct DataTable
      //var row = table.rows(dataIndex).nodes().to$(); // Correct row?
      var rowkey = table.rows(dataIndex).nodes().to$().data("primarykey");
      console.log('key: '+rowkey); // Shows 'key: undefined' in console.

      // If we've seen the row before (already in the array), filter it out.
      // Otherwise, return true and add it to the array
      if ($.inArray(rowkey,rowkeys) > -1) return false;
      else {
        rowkeys.push(rowkey);
        return true;
      }
    }
  );   

Solution

  • This filter is applying to multiple tables, so it would need to be whatever table is currently being filtered, if possible. Each table has a unique id, but share a class attribute.

    You need to have a if check to limit your filter to work on only specified tables.

     if (settings.nTable.id === "yourTableId" || settings.nTable.id === "anotherTableId") { 
    
     }
    

    you can also do the if check on class

    if ($(settings.nTable).hasClass('yourClass')) { 
    
    }
    

    // I want rowkey to be the data-primarykey attribute of the tr element

    You can get that with in the settings variable in the callback and using the counter variable too in combination.

    enter image description here

    So all you need to do is to have this line

    var rowkey = $(settings.aoData[counter].nTr).data('primarykey');
    

    Here is a Working example where I use this filter logic.

    Note: The above example has a static HTML table which I think is not a problem as we are more concentrated on the filter logic. Also the filter works only when you type in something in the search box.

    So the final logic would look like below

    var rows = [];
    
    $.fn.dataTableExt.afnFiltering.push(
      function(settings, data, dataIndex, rowObj, counter) {
        if (settings.nTable.id === "yourTableId") {   // change (1)
          if (counter === 0) rows = [];
    
          // I want rowkey to be the data-primarykey attribute of the tr element
          var rowkey = $(settings.aoData[counter].nTr).data('primarykey'); // change (2)
    
          // If we've seen the row before (already in the array), filter it out.
          // Otherwise, return true and add it to the array
          if ($.inArray(rowkey, rows) > -1) return false;
          else {
            rows.push(rowkey);
            return true;
          }
        }
      }
    );