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.