0

I'm trying to implement a footerCallback in DataTables that computes a conditional sum of each column, based on a cell that's in a different column in the same row. Here's a demo of my setup: https://jsfiddle.net/rantoun/552y9j90/13/

HTML:

<table id="table1">
  <thead>
    <tr>
      <th>Fruit</th>
      <th>sumCondition</th>
      <th># Eaten</th>
      <th># Remaining</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <th></th>
      <th align="center">Count</th>
      <th align="left"></th>
      <th align="left"></th>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>Apples</td>
      <td>Use</td>
      <td>3</td>
      <td>8</td>
    </tr>
    <tr>
      <td>Oranges</td>
      <td>Use</td>
      <td>6</td>
      <td>5</td>
    </tr>
    <tr>
      <td>Bananas</td>
      <td>Ignore</td>
      <td>2</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

jQuery:

$("#table1").DataTable({
  "paging": false,
  "searching": false,
  "info": false,    
    "footerCallback": function ( row, data, start, end, display ) {

      var columns = [2, 3];
      var api = this.api();

      _.each(columns, function(idx) {

          var total = api
              .column(idx)
              .data()
              .reduce(function (a, b) {
                  return parseInt(a) + parseInt(b);
              }, 0)         

                $('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
      })

  }
});

Specifically, my goal is for the footerCallback to only sum the rows where "Ignore" is NOT in the Condition column. Hopefully this is clear and any help is appreciated.

nkbved
  • 79
  • 3
  • 11

2 Answers2

2

I solved this by getting the current index of the summing value in the reduce function and then using the index to access the respective value in the condition cell. Below is the new jQuery code:

$('#table1').DataTable({
  'paging': false,
  'searching': false,
  'info': false,
  'footerCallback': function (row, data, start, end, display) {


    var columns = [2, 3];
    //console.log(data);
    var api = this.api();

    // Get sumCondition and put in array     

    _.each(columns, function (idx) {

      var total = api
        .column(idx)
        .data()
        .reduce(function (a, b) {
          // Find index of current value for accessing sumCondition value in same row
          var cur_index = api.column(idx).data().indexOf(b);
          if (api.column(1).data()[cur_index] != 'Ignore') {
            return parseInt(a) + parseInt(b);
          } else {
            return parseInt(a);
          }
        }, 0);

      $('tr:eq(0) th:eq(' + idx + ')', api.table().footer()).html(total);
    });

  },
});

Working Fiddle: https://jsfiddle.net/rantoun/552y9j90/14/

Saeed Zhiany
  • 2,051
  • 9
  • 30
  • 41
nkbved
  • 79
  • 3
  • 11
0

There is a problem when rows in column have identical numbers. Where "if" statement is not applied. Base on this topic and answer: Jquery Datatable sum conditional footer callback not displaying correct result

HTML:

<table id="table1">
  <thead>
    <tr>
      <th>Fruit</th>
      <th>sumCondition</th>
      <th># Eaten</th>
      <th># Remaining</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <th></th>
      <th align="center">Count</th>
      <th align="left"></th>
      <th align="left"></th>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>Apples</td>
      <td>Use</td>
      <td>3</td>
      <td>8</td>
    </tr>
    <tr>
      <td>Oranges</td>
      <td>Use</td>
      <td>6</td>
      <td>5</td>
    </tr>
    <tr>
      <td>Bananas</td>
      <td>Ignore</td>
      <td>6</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

jQuery:

$("#table1").DataTable({
  "paging": false,
  "searching": false,
  "info": false,    
    "footerCallback": function ( row, data, start, end, display ) {
        
      var columns = [2, 3];
      //console.log(data);
      var api = this.api();
      
      // Get sumCondition and put in array     
      
      _.each(columns, function(idx) {

    var total = total = api.data().reduce(function(a, b) {
      var prev = 0;
      var next = 0;
      if (Array.isArray(a)) {
        if (a[1] !== "Ignore") {
          prev = parseInt(a[idx]);
        }

      } else {
        prev  = a;
      }
      if (b[1] !== "Ignore") {
          next = parseInt(b[idx]);
      }
      return prev + next;
              }, 0)         

                $('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
      })
      
  }
});

Working Fiddle: https://jsfiddle.net/79fx6aqg/1/

Hristian Yordanov
  • 650
  • 1
  • 6
  • 25