Kendo Grid TemplateFooter聚合应用Filters后未刷新问题(Kendo jQuery)
问题根源解析
嘿,这个问题我之前帮不少开发者排查过,核心原因很明确:你用的自定义聚合函数默认只会基于原始完整数据集计算,不会自动跟随筛选后的数据集更新。
Kendo Grid的内置聚合(比如sum)是和数据源绑定的,当你做筛选、分页这类操作时,数据源会触发change事件,内置聚合会自动重新计算当前显示的数据集的聚合值。但自定义聚合函数不一样,它默认不会监听数据源的变化,不管你怎么筛选,它都会一直用最开始的全量数据来计算求和,这就导致筛选后Grid内容变了,但求和数字纹丝不动。
两种解决方案
针对这个问题,有两种靠谱的解决思路,你可以根据自己的场景选:
思路一:改用内置聚合(推荐)
如果你的字符串格式浮点数是标准格式(比如"123.45"、"67.8"这种),其实完全不需要自定义聚合函数,只要让Kendo自动把字符串转成数值类型就行,这样就能用内置的sum,它会自动响应筛选变化。
具体配置如下:
// 数据源配置 var dataSource = new kendo.data.DataSource({ data: yourJsonData, // 你的原始JSON数据 schema: { model: { fields: { // 把目标字段设为number类型,同时用parse处理字符串转数值 amount: { type: "number", parse: function(value) { // 处理空值或者非数字情况,避免NaN return isNaN(parseFloat(value)) ? 0 : parseFloat(value); } } } }, // 直接用内置sum聚合 aggregate: [{ field: "amount", aggregate: "sum" }] }, filterable: true // 开启筛选 }); // Grid配置 $("#grid").kendoGrid({ dataSource: dataSource, columns: [ // 其他列... { field: "amount", title: "金额", // 页脚模板直接用内置的sum值,还能格式化显示 footerTemplate: "总计: #= kendo.toString(sum, 'n2') #" } ], filterable: true, sortable: true });
这种方式最省心,因为内置聚合已经帮你处理了所有数据源变化的场景,不用自己写额外的事件监听。
思路二:手动监听数据源变化,更新自定义聚合
如果你的字符串格式比较特殊(比如带货币符号、千分位分隔符),必须用自定义聚合函数,那就要手动监听数据源的change事件,每次数据变化时重新计算聚合值并更新页脚。
步骤如下:
- 先定义你的自定义求和函数:
function customSum(items) { return items.reduce(function(total, item) { // 这里根据你的字符串格式做转换,比如去掉$符号再转数值 var num = parseFloat(item.amount.replace(/\$/, "")) || 0; return total + num; }, 0); }
- 配置数据源和Grid,然后监听
change事件:
var dataSource = new kendo.data.DataSource({ data: yourJsonData, schema: { model: { fields: { amount: { type: "string" } } }, // 初始聚合用自定义函数 aggregate: [{ field: "amount", aggregate: customSum }] }, filterable: true }); var grid = $("#grid").kendoGrid({ dataSource: dataSource, columns: [ // 其他列... { field: "amount", title: "金额", // 初始页脚模板 footerTemplate: "总计: 0.00" } ], filterable: true, sortable: true }).data("kendoGrid"); // 监听数据源的change事件,每次筛选、分页后重新计算 dataSource.bind("change", function() { // 获取当前筛选后的数据集 var filteredItems = this.view(); // 计算更新后的总和 var newSum = customSum(filteredItems); // 更新页脚的显示内容,注意替换成你的列索引(从0开始) var footerCell = grid.tfoot.find("td:eq(1)"); footerCell.text("总计: " + newSum.toFixed(2)); });
这样每次筛选后,数据源触发change事件,就会重新计算当前显示数据的总和,然后更新页脚的数值。
内容的提问来源于stack exchange,提问作者HamzStramGram




