Layui数据表格合并单元格
零、序言
最近做的一个项目中遇到一个需求,需要合并动态加载数据的数据表格中相同的单元格,但需要区分开不同的父级。
原始数据:
需要合并后的效果:
一、搜寻解决方案
项目使用的是 layui
前端框架,但是在官网的文档中没有找到可行的支持,不过最后在网上找到了 layui
单元格合并的解决方案。
原博客:layui 动态表格之合并单元格
作者使用 layui
数据表格的 done
事件,在数据表格渲染完成后执行自定义的合并单元格方法。我稍作修改后如下所示。
//layui数据表格渲染完成时触发的回调方法
done : function(res, curr, count) {
//调用自定义的合并单元格方法
mergeFields(res);
}
//自定义的合并单元格方法
function mergeFields(res) {
//表格所有数据
var data = res.data;
//所有行
var trArray = $(".layui-table-body>.layui-table").find("tr");
//需要合并的列索引和列名称
var mergeColums = [
{
columIndex: '0',
columName: 'goodsName'
},
{
columIndex: '1',
columName: 'goodsNameSum'
},
{
columIndex: '2',
columName: 'goodsBrand'
},
{
columIndex: '3',
columName: 'goodsBrandSum'
}
];
//这里遍历所有要合并的列
for (var i = 0; i < mergeColums.length; i++) {
//需要合并的开始行索引
var mergeStartIndex = 0;
//需要合并的格子数
var mergeCount = 1;
//这里遍历表格所有数据,从第二行开始,第一行不需要判断
for (var j = 1; j < res.data.length; j++) {
//当前行的当前列
var currentTrCurrentTd = trArray.eq(j).find("td").eq(mergeColums[i].columIndex);
//需要合并的开始行的当前列
var startTrCurrentTd = trArray.eq(mergeStartIndex).find("td").eq(mergeColums[i].columIndex);
//后一行的值与前一行的值做比较,相同就需要合并
if (data[j][mergeColums[i].columName] === data[j - 1][mergeColums[i].columName]) {
mergeCount += 1;
//相同列的第一列增加rowspan属性
startTrCurrentTd.attr("rowspan", mergeCount);
//当前行隐藏
currentTrCurrentTd.css("display", "none");
} else {
//一旦前后两行的当前列的值不一样了,那么需要合并的开始行需要从当前的j行重新开始
mergeStartIndex = j;
//一旦前后两行的值不一样了,那么需要合并的格子数mark就需要重新计算
mergeCount = 1;
}
}
}
}
运行后发现,相同的单元格确实得到了合并。但我们可以发现 笔记本电脑
和 台式电脑
下的相同品牌 戴尔
合并到了一起,这并不是我们的预期效果。
二、动手改善优化
所以自己动手修改优化算法,加入当前列和前一列之间的判断,防止非同一父级却合并到一起的情况出现。修改后如下所示。
function mergeFields(res) {
//表格所有数据
var data = res.data;
//所有行
var trArray = $(".layui-table-body>.layui-table").find("tr");
//需要合并的列索引和列名称
var mergeColums = [
{
columIndex: '0',
columName: 'goodsName'
},
{
columIndex: '1',
columName: 'goodsNameSum'
},
{
columIndex: '2',
columName: 'goodsBrand'
},
{
columIndex: '3',
columName: 'goodsBrandSum'
}
];
//这里遍历所有要合并的列
for (var i = 0; i < mergeColums.length; i++) {
//需要合并的开始行索引
var mergeStartIndex = 0;
//需要合并的格子数
var mergeCount = 1;
//这里遍历表格所有数据,从第二行开始,第一行不需要判断
for (var j = 1; j < res.data.length; j++) {
//当前行的前一列
var currentTrPreviousTd = i != 0 ? trArray.eq(j).find("td").eq(mergeColums[i].columIndex - 1) : null;
//当前行的当前列
var currentTrCurrentTd = trArray.eq(j).find("td").eq(mergeColums[i].columIndex);
//需要合并的开始行的当前列
var startTrCurrentTd = trArray.eq(mergeStartIndex).find("td").eq(mergeColums[i].columIndex);
//后一行的值与前一行的值做比较,相同就需要合并
if (data[j][mergeColums[i].columName] === data[j - 1][mergeColums[i].columName] && (currentTrPreviousTd == null || currentTrPreviousTd.css("display") == "none")) {
mergeCount += 1;
//相同列的第一列增加rowspan属性
startTrCurrentTd.attr("rowspan", mergeCount);
//当前行隐藏
currentTrCurrentTd.css("display", "none");
} else {
//一旦前后两行的当前列的值不一样了,那么需要合并的开始行需要从当前的j行重新开始
mergeStartIndex = j;
//一旦前后两行的值不一样了,那么需要合并的格子数mark就需要重新计算
mergeCount = 1;
}
}
}
}
大功告成!
License:
CC BY 4.0