由于项目的需要,datatables表格需要对一些相同的数据单元进行行合并,但是网上搜索了半天,能实现行的合并,但是在经过数据筛选或者分页后又会还原。在此记录下自己的解决办法,希望能帮到需要的人。。。
1、合并原理
在datatables中,对于行的合并好像并没有给出具体的api,这里行的合并都是通过rowspan来实现,所以要合并多少行,这里需奥数据来标明。所以我做sql查询的时候,把数据进行了分组,然后给出一个字段来表示需要设置rowsapn的值,根据此值来添加相应的rowspan属性,从而实现合并行。
2、具体实现
1、查询的数据格式
在查询出来的数据中,有ROWN和MAXNUM两列,ROWN表示组内的顺序,MAXNUM表示组内最大的ROW值。
2、JS代码
网上的合并行都是将合并代码写在createdCell 当中,但是在对表格进行重绘后就会产生还原的问题,所以在下面的代码中我仅仅是把代码写到rowCallback 中而已,具体代码看下面:
首先在这里封装了一个datatables的方法:
var $table;
/**
* 初始化Datatablas 包含分页,单列排序
* @param {any} url 请求路径
* @param {any} columns 列初始化
* @param {any} columnDefs 自定义列显示
*/
function initTable(url, columns, columnDefs, loadSuccess, rowCallBack) {
$table = $('#data-table').DataTable({
"language": {
"url": _datatablesLangUrl //全局变量,定义在_layout中
},
"dom": _defaultDom,
"ordering": true,
//"lengthChange": false, //是否允许用户改变表格每页显示的记录数,false时隐藏,默认true
'order': [],//初始排序列
//'select': true,
"processing": true,
"serverSide": true,
"pageLength": 25,
"scrollX": true,
"scrollY": '50vh',
"scrollCollapse": true,
"destroy": true,
"ajax": {
"url": url,
"type": "POST"
},
"rowCallback": function (row, data, index) {
//console.log(data);
if (rowCallBack)
rowCallBack(row, data, index);
},
"columns": columns,
"columnDefs": columnDefs
});
$table.on('init.dt', function () {
if (loadSuccess)
loadSuccess();
})
}
loadSuccess和rowCallBack都是回调方法。
var columns = [
{"title":"", data: null, "visible": true },
{"title":"", data: null, "visible": true },
{"title":"", "width": "30px", "data": null },// 序号列
{"title":"", "data": "ID", "visible": false },
{"title":"EXPRESSNUMBER", "data": "EXPRESSNUMBER" },
{"title":"EXPRESSCOMPANY", "data": "EXPRESSCOMPANY" },
{"title":"INVOICENO", "data": "INVOICENO" },//6
{"title":"CUSTOMERCODE", "data": "CUSTOMERCODE" },
{"title":"CUSTOMERFULLNAME", "data": "CUSTOMERFULLNAME" },
{"title":"CREATEUSERNAME", "data": "CREATEUSERNAME", orderable: !1 },
{"title":"CREATETIME", "data": "CREATETIME", orderable: !1 },
{"title":"LOGUSERNAME", "data": "LOGUSERNAME", orderable: !1 },
{"title":"LOGTIME", "data": "LOGTIME", orderable: !1 },
{"title":"EXPRESSENCODINGID", "data":"EXPRESSENCODINGID","visible":false},
{"title":"rown", "data":"rown","visible":false},
{"title":"maxnum", "data":"maxnum","visible":false},
];
var columnDefs = [{
targets: 0,
orderable: !1,
render: function (data, type, row, meta) {
//在列渲染时做的一些额外操作,比如颜色字体等等
},
{
},
...........
}
上面都是为表格初始化做的一些列定义等操作,网上搜索有详细的教程,下面就是行合并了,代码就是在rowCallBack当中:
function rowCallBack(row, data, index){
//row代表表格的每一行,每行数据都会进入这个方法走一遍
console.log(data)//data,就是当前行的数据
if(data.rown == data.maxnum){
$(row).find("td").eq(3).attr('rowspan', data.maxnum);
$(row).find("td").eq(4).attr('rowspan', data.maxnum);
}else{
$(row).find("td").eq(3).remove();
$(row).find("td").eq(3).remove();
}
}
在这个rowCallBack当中,我对数据进行了判断,就是将rown和maxnum相等的行合并,不相等的删除掉。当然这里的操作,得看自己的数据格式,如果对于数据库查询出来的数据,每一组内的rown并不是从大到小的,而是从小到达的,你也可以判断data.rown == 1的时候进行行合并 ,其他条件下进行单元格的删除。 上面代码中eq(n)这个值由自己决定合并哪一列(从左到右 数起,其实为0),这里解释下上面代码中为什么会对eq(3)进行两次remove(),这是因为在第一次对eq(3)进行remove操作后,本来的....eq(4).remove(),由于前一列被删除,这里的第4列就变成列第3列,所以第二次对eq(3)的remove就是对eq(4)的remove()。
对于上面sql查询出来的数据格式,主要是用了Oracle的partition by分析函数,下面简单介绍下原理:
对于数据表的数据,我分为三个步骤得到上面的数据格式:
1、第一次,使用partition by分析函数分组:
select row_number() over(partition by t.expressnumber order by t.createtime desc) rown ,t.* from temp t
上面的sql可以得到一个分组的数据,也就得到了需要用到的 rown
2、
SELECT MAX(tt.rown) maxnum,tt.expressnumber from t2 tt group by tt.expressnumber
这里的t2表就是第一步查询得出的结果集,这个可以使用Oracle的with实现
3、对上面的两个结果集进行left join
with t2 as --第一步
(
select row_number() over(partition by t.expressnumber order by t.logtime desc) rown ,t.* from temp t
),
t3 as --第二步
(
SELECT MAX(tt.rown) maxnum,tt.expressnumber from t2 tt group by tt.expressnumber
)
--第三步
select tt2.*,tt3.maxnum from t2 tt2
left join t3 tt3
on tt2.expressnumber = tt3.expressnumber
上面的代码基本就能得到数据,如果发现组内顺序或者组外顺序不尽人意,进行下组外组内排序就能得到数据了。
上面只是我自己的一些见解,请大家批评指正。