How to show dynamic totals in DataTables footer with scrollX enabled?
How to show dynamic totals in DataTables footer with scrollX enabled?

```
I am working with jQuery DataTables where I have a large HTML table (around 40 columns).
- I added a <tfoot> row to display totals for each column.
- I am calculating totals in footerCallback and it works fine.
- I also enabled scrollX: true to make the wide table scrollable.
The problem:
- When I enable scrollX, the footer totals do not align properly with the header/columns.
- Without scrollX, alignment is correct but the table overflows outside the screen.
What I want:
- Properly aligned footer totals even when scrollX: true.
- A clean way to visualize the totals row (maybe bold, highlighted, sticky footer, etc.).
table = $('#callsTable').DataTable({
destroy: true,
ajax: {
url: '@Url.Action("GetCallsPerDay", "Reports")',
type: 'GET',
data: {
shift: shiftValue,
month: monthValue,
year: yearValue
},
dataSrc: ''
},
layout: {
topStart: {
buttons: [
{ extend: 'copyHtml5', text: '<i class="fa fa-files-o"> Copy</i>', titleAttr: 'Copy' },
{ extend: 'excelHtml5', text: '<i class="fa fa-file-excel-o"> Excel</i>', titleAttr: 'Excel' },
{ extend: 'csvHtml5', text: '<i class="fa fa-file-text-o"> CSV</i>', titleAttr: 'CSV' },
]
}
},
responsive: false,
stateSave: false,
pageLength: 50,
scrollX: true,
scrollY: "500px",
scrollCollapse: true,
fixedHeader: true,
paging: false,
sortable: false,
language: {
info: "Total Records: TOTAL",
infoEmpty: "No records available"
},
columns: [
{ data: "fF_ID", className: 'dt-left', orderable: false },
{ data: "mpO_CODE", sortable: false },
{ data: "mpO_NAME", sortable: false },
{ data: "mobilE_NO", sortable: false },
{ data: "manageR_CODE", sortable: false },
{ data: "manageR_NAME", sortable: false },
{ data: "d_1" , className: 'dt-left', sortable: false },
{ data: "d_2" , className: 'dt-left', sortable: false },
{ data: "d_3" , className: 'dt-left', sortable: false },
{ data: "d_4" , className: 'dt-left', sortable: false },
{ data: "d_5" , className: 'dt-left', sortable: false },
{ data: "d_6" , className: 'dt-left', sortable: false },
{ data: "d_7" , className: 'dt-left', sortable: false },
{ data: "d_8" , className: 'dt-left', sortable: false },
{ data: "d_9" , className: 'dt-left', sortable: false },
{ data: "d_10" , className: 'dt-left', sortable: false },
{ data: "d_11" , className: 'dt-left', sortable: false },
{ data: "d_12" , className: 'dt-left', sortable: false },
{ data: "d_13" , className: 'dt-left', sortable: false },
{ data: "d_14" , className: 'dt-left', sortable: false },
{ data: "d_15" , className: 'dt-left', sortable: false },
{ data: "d_16" , className: 'dt-left', sortable: false },
{ data: "d_17" , className: 'dt-left', sortable: false },
{ data: "d_18" , className: 'dt-left', sortable: false },
{ data: "d_19" , className: 'dt-left', sortable: false },
{ data: "d_20" , className: 'dt-left', sortable: false },
{ data: "d_21" , className: 'dt-left', sortable: false },
{ data: "d_22" , className: 'dt-left', sortable: false },
{ data: "d_23" , className: 'dt-left', sortable: false },
{ data: "d_24" , className: 'dt-left', sortable: false },
{ data: "d_25" , className: 'dt-left', sortable: false },
{ data: "d_26" , className: 'dt-left', sortable: false },
{ data: "d_27" , className: 'dt-left', sortable: false },
{ data: "d_28" , className: 'dt-left', sortable: false },
{ data: "d_29" , className: 'dt-left', sortable: false },
{ data: "d_30" , className: 'dt-left', sortable: false },
{ data: "d_31" , className: 'dt-left', sortable: false },
{ data: "totaL_MPO_CALLS" , className: 'dt-left', sortable: false }
],
footerCallback: function (row, data, start, end, display) {
var api = this.api();
var intVal = function (i) {
return typeof i === 'string'
? i.replace(/[\$,]/g, '') * 1
: typeof i === 'number'
? i : 0;
};
for (var col = 6; col <= 37; col++) {
var total = api
.column(col, { page: 'current' })
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
$(api.column(col).footer()).html(total);
}
}
});
FF ID | MPO Code | MPO Name | Mobile No | Manager Code | Manager Name | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 | D11 | D12 | D13 | D14 | D15 | D16 | D17 | D18 | D19 | D20 | D21 | D22 | D23 | D24 | D25 | D26 | D27 | D28 | D29 | D30 | D31 | Total Calls |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Grand Total |
Answers
I built this test case and using
scrollX
withfooterCallback
seems to work as expected.https://live.datatables.net/coqucuka/1/edit
Possibly you aren't loading the proper Datatables styling integration for the style framework, Bootstrap for example, that you are using. Make sure you have all the proper files using the Download builder.
Styling issues are difficult to debug from screenshots. If the above doesn't help then please provide a link to a test case replicating the issue. You can update mine if you wish.
https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case
Kevin
Nice use of footerCallback! The misalignment with scrollX is common since header, body, and footer are split. Running columns.adjust() or tweaking CSS usually fixes it. A similar case is discussed here: Footer not aligning with scrollX
.