Home > other >  footerCallback with duplicate cell numbers
footerCallback with duplicate cell numbers

Time:06-01

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 >

  <div >


  <table id="example"  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/

CodePudding user response:

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.

  • Related