1

I am trying to use footerCallback with conditional on another cell. I see and replay to this question: DataTables footerCallback - conditional on another cell.

There I wrote that when cells are with identical numbers there is wrong sum. In my code I don't use _each. I tried to implement it in my code but I need to create different arithmetic operation on each sum.

Here is the case with wrong sum when salary(There I cut the zeros for simplicity) of System Architect need to be excluded:

HTML:

<div class="row">

  <div class="large-12 columns">


  <table id="example" class="display nowrap table1" cellspacing="0" width="100%">
      <thead>
        <tr>
          <th>Seq.</th>
          <th>Name</th>
          <th>Position</th>
          <th>Salary</th>
        </tr>
      </thead>
      <tfoot>
        <tr>
          <th>Seq.</th>
          <th>Name</th>
          <th>Position</th>
          <th>Salary</th>
        </tr>
      </tfoot>
      <tbody>
        <tr>
          <td>1</td>
          <td>Tiger Nixon</td>
          <td>System Architect</td>
          <td>$1</td>
        </tr>
        <tr>
          <td>1</td>
          <td>Garrett Winters</td>
          <td>Accountant</td>
          <td>$1</td>
        </tr>
        <tr>
          <td>3</td>
          <td>Ashton Cox</td>
          <td>Junior Technical Author</td>
          <td>$3</td>
        </tr>
        <tr>
          <td>4</td>
          <td>Cedric Kelly</td>
          <td>Senior Javascript Developer</td>
          <td>$4</td>
        </tr>
        <tr>
          <td>5</td>
          <td>Airi Satou</td>
          <td>Accountant</td>
          <td>$5</td>
        </tr>
   
      </tbody>
    </table>

  </div>

</div>  

jQuery:

 $(document).ready(function() {
    var table = $('#example').DataTable( {
        rowReorder: {
        selector: 'td:nth-child(2)'
      },
      responsive: true,
      scrollX: true,
      scrollY: "80vh",
        scrollCollapse: true,
            paging: true,
      lengthChange: false,
      lengthMenu: [ [10, 25, -1], [10, 25, "All"] ],
      "order": [[ 0, "asc" ]],
      "footerCallback": function ( row, data, start, end, display ) {
            var api = this.api(), data;
 
            // Remove the formatting to get integer data for summation
            var intVal = function ( i ) {
                return typeof i === 'string' ?
                    i.replace(/[\$,]/g, '')*1 :
                    typeof i === 'number' ?
                        i : 0;
            };
 
            // Total over all pages
            total = api
                .column( 3 )
                .data()
      .reduce(function (a, b) {
            var cur_index = api.column(3).data().indexOf(b);
            if (api.column(2).data()[cur_index] != "System Architect") {
            return intVal(a) + intVal(b);
          }
          else { return intVal(a); }
      }, 0 );
 
            // Total over this page
            pageTotal = api
                .column( 3, { page: 'current'} )
                .data()
                .reduce( function (a, b) {
                    return intVal(a) + intVal(b);
                }, 0 );
 
            // Update footer
            $( api.column( 3 ).footer() ).html(
                '$'+total+'/ all $'+pageTotal
            );
        },
        buttons: ['pdf', 'print']
    } );
 
    table.buttons().container()
        .appendTo( '#example_wrapper .small-6.columns:eq(0)' );
} );
   $(document).foundation();

Fiddle with the problem: https://jsfiddle.net/62bmu4so/

andrewJames
  • 19,570
  • 8
  • 19
  • 51
Hristian Yordanov
  • 650
  • 1
  • 6
  • 25
  • Can you clarify what the problem is? The fiddle looks correct to me. I see `$10/ all $14`, where `10` is the sum of everything except "Senior Javascript Developer", and `14` is the sum of everything. What do you expect to see? And why? – andrewJames May 31 '22 at 12:28
  • 1
    Sorry @andrewJames I forgot to change to exclude by "System Architect". Need to be $13/ all $14. There is new fiddle... – Hristian Yordanov May 31 '22 at 12:43

1 Answers1

1

I would change your approach for the filtered total to this:

filteredTotal = api.rows().data().reduce(function (a, b) {
  salary = b[2] === "System Architect" ? 0 : intVal(b[3]);
  return a + salary;
}, 0 );
              
console.log(filteredTotal); // just for demo/testing

So, instead of processing only one column in your reduce function, I would process by rows() instead.

This means the value of b in the reduce function is an array containing the current row's data. Using that we can check if the job title in b[2] matches our filter value - and force b[3] to zero if b[2] matches.

This means:

  • you are no longer skipping any of the sums you need to perform in the reduce()
  • you no longer need to perform additional index lookup steps.

Comment: "where "Senior Javascript Developer" can be excluded too":

You could do it like this - separating the process into 2 steps for clearer code:

// filterMe will be true or false:
filterMe = b[2] === "System Architect" || b[2] === "Senior Javascript Developer";

// if filterMe is true then use 0, otherwise use the actual amount from b[3]:
salary = filterMe ? 0 : intVal(b[3]);

I have not tested this, but it should work.

andrewJames
  • 19,570
  • 8
  • 19
  • 51
  • Thanks that works. One more thing can you edit your answer where "Senior Javascript Developer" can be excluded too, please? – Hristian Yordanov May 31 '22 at 13:57
  • do you know why result in my case(ajax) is always `0` when using rows()? When I change to `column()` I see result different from 0... – Hristian Yordanov Jun 01 '22 at 07:24
  • The code in your question does not use Ajax. If you have changed to using Ajax now, then please edit your question and add these new details at the end of the question. Show the relevant code and show a sample of your JSON data (as text). – andrewJames Jun 01 '22 at 10:31
  • I make new question for this [link](https://stackoverflow.com/questions/72462047/footercallback-exclude-rows-and-sum-it-with-json-data). Check it, please. – Hristian Yordanov Jun 01 '22 at 12:40