Tabulator数据树父行动态聚合 配合topCalc及筛选功能实现问题
Tabulator数据树父行动态聚合+顶部计算+筛选协同适配问题
我在使用Tabulator的过程中想要实现多个功能的协同适配,目前已经接近可用方案,但不断遇到新问题,恳请各位提供帮助。
我有一组配置了子节点的数据集,用于渲染数据树(dataTree)。
我的核心需求是在父行展示子节点的聚合数据,具体来说:父行显示该节点下所有子项的总浏览量(total-views),子行则展示对应单日的浏览量。
上述功能本身实现难度不大,但当我需要同时接入顶部聚合计算(topCalc)和表格筛选功能时就出现了问题。
我的示例代码如下:
let tabledata = [ {id:1, isParent: true, title:"Making sense", date:"01/02/2016", _children:[ {date:"01/02/2016", title:"Making sense 1", views: 204}, {date:"07/02/2017", title:"Making sense 2", views: 21}, ]}, {id:1, isParent: true, title:"Restoring sanity", date:"22/05/2017", _children:[ {date:"22/05/2017", title:"Restoring sanity 1", views: 12}, {date:"11/02/2018", title:"Restoring sanity 2", views: 51}, {date:"04/04/2018", title:"Restoring sanity 3", views: 103}, ]}, ] const topCalcViews = function (values, data, calcParams ) { let total = 0; values.forEach(function (value) { if (value > 0) { total += value; } }); return total; } const table = new Tabulator("#table", { height:400, data:tabledata, layout:"fitColumns", dataTree: true, debugInvalidOptions: true, columns:[ {title:"Title", field:"title" }, {title:"Publish date", field:"date", hozAlign:"left", headerFilter:true}, {title:"views", field:"views", topCalc: topCalcViews, formatter: function (cell, formatterParams, onRendered) { let data = cell.getData(); let totalViews = 0; if (data.isParent) { data._children.forEach(child => { totalViews += child.views; }); return totalViews; } else return cell.getValue(); } } ], });
从运行效果可以看到,除了topCalc功能异常外,其余逻辑都可以正常运行。我判断是因为我使用了formatter渲染父行浏览量,原始数据中没有对应存储值,所以连内置求和方法也无法生效。
我期望的效果是:触发筛选操作后,父行能重新计算当前可见子项的总浏览量,而不是始终显示所有子项的固定总和。
我已经尝试过多种解决方法均未成功:
- 替换formatter为mutator,仍然存在问题
- 为topCalc配置dataTreeChildColumnCalcs属性,父行总浏览量依然不会更新
- 主动调用父行重渲染方法也没有效果
补充说明:该表格仅用于数据展示,不需要支持编辑操作,导出会使用单独的表格实现,所以使用mutator或者formatter方案都可以接受。
解决方案
无需重写Tabulator原型,仅调整topCalc逻辑、views列formatter逻辑,新增筛选后刷新规则即可实现需求:
const table = new Tabulator("#table", { height:400, data:tabledata, layout:"fitColumns", dataTree: true, debugInvalidOptions: true, // 新增筛选完成后刷新父行逻辑 dataFiltered: function() { table.getRows().forEach(row => { if(row.getData().isParent) row.reformat() }) }, columns:[ {title:"Title", field:"title" }, {title:"Publish date", field:"date", hozAlign:"left", headerFilter:true}, { title:"views", field:"views", // 重写topCalc,直接累加所有可见子行的浏览量,避免父行重复计算 topCalc: function() { let total = 0 table.getRows("visible").forEach(row => { const rowData = row.getData() if(!rowData.isParent) total += rowData.views || 0 }) return total }, formatter: function (cell) { const row = cell.getRow() const data = cell.getData() if (data.isParent) { let totalViews = 0 // 仅统计当前父行下可见的子项浏览量 row.getTreeChildren().forEach(child => { if(child.isVisible()) totalViews += child.getData().views || 0 }) return totalViews } return cell.getValue() } } ], })
内容的提问来源于stack exchange,提问作者Martin van Soest
相关产品推荐
相关产品推荐

