DataTable footerCallback求和报错(nTf未定义)求助
问题:DataTables tfoot求和功能报错,无法计算总值
现有代码可正常渲染表格tbody数据,但通过tfoot实现最后一列求和时触发错误,控制台输出:
Uncaught TypeError: Cannot set properties of undefined (setting 'nTf') at Fb (jquery.dataTables.min.js:40:282) at Ba (jquery.dataTables.min.js:62:151) at f (jquery.dataTables.min.js:108:98) at HTMLTableElement.<anonymous> (jquery.dataTables.min.js:108:184) at Function.each (jquery-3.6.0.min.js:2:3003) at S.fn.init.each (jquery-3.6.0.min.js:2:1481) at S.fn.init.u [as dataTable] (jquery.dataTables.min.js:98:199) at HTMLButtonElement.<anonymous> (jsdashboard.js:21510:21) at HTMLButtonElement.dispatch (jquery-3.6.0.min.js:2:43064) at v.handle (jquery-3.6.0.min.js:2:41048)
原因分析
- tfoot列数不匹配:表格thead共4列,但tfoot中
<td COLSPAN="2">+<td COLSPAN="3">总跨度为5,超出thead列数,DataTables初始化时会校验表头/表尾列数一致性,触发报错。 - 重复初始化DataTables:每次点击按钮都会重新调用
.DataTable(),未销毁已存在的实例,引发冲突。 - footerCallback数据处理错误:手动拼接tbody后,DataTables的
data()方法无法正确识别行数据结构,且直接用字符串类型的数值相乘会导致计算异常。
解决方案
- 修正tfoot列跨度:确保tfoot列跨度总和与thead列数一致(4列)。
- 初始化前销毁旧实例:避免重复初始化引发的冲突。
- 优化数据逻辑:直接将原始数据传入DataTables,由组件渲染tbody,确保
footerCallback能正确访问数据字段;将字符串数值转为数字后计算总和。
修正后的代码
JavaScript部分
var data = [ {Id: "1", Quantidade: "14", Preco: "3.10"}, {Id: "2", Quantidade: "5", Preco: "1.80"}, {Id: "3", Quantidade: "3", Preco: "0.45"}, {Id: "4", Quantidade: "4", Preco: "9.83"}, {Id: "5", Quantidade: "2", Preco: "15.30"}, {Id: "6", Quantidade: "3", Preco: "9.98"}, ]; $('.enc-per').on("click", function() { // 销毁已存在的DataTables实例 if ($.fn.DataTable.isDataTable('#encofinal')) { $('#encofinal').DataTable().destroy(); } $('#encofinal').DataTable({ data: data, columns: [ { data: 'Id', className: 'text-center text-muted' }, { data: 'Quantidade', className: 'text-center text-muted' }, { data: 'Preco', className: 'text-center text-muted' }, { data: null, className: 'text-center text-muted', render: function(data) { return (parseFloat(data.Quantidade) * parseFloat(data.Preco)).toFixed(2); } } ], fixedHeader: { header: true, footer: true }, footerCallback: function() { const api = this.api(); // 计算过滤后数据的总和 const sumProduct = api.rows({search:'applied'}).data().reduce((total, row) => { return total + parseFloat(row.Quantidade) * parseFloat(row.Preco); }, 0).toFixed(2); $('#sumproduct').text(sumProduct); } }); });
HTML部分
<link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet"> <link href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.bootstrap5.min.css" rel="stylesheet"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/1.11.4/js/dataTables.bootstrap5.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.2.2/js/buttons.bootstrap5.min.js"></script> <button type="button" class="btn btn-info enc-per" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button> <table class="align-middle mb-0 table table-border table-striped table-hover encofinal" id="encofinal"> <thead> <tr> <th class="text-center">Pedido</th> <th class="text-center">Qtd</th> <th class="text-center">Preço</th> <th class="text-center">Valor</th> </tr> </thead> <tbody></tbody> <tfoot> <tr> <td colspan="3" class="text-end">Valor Total:</td> <td class="text-center"><span id="sumproduct"></span>€</td> </tr> </tfoot> </table>
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

