数据表格组件是大家最常用的组件之一,easyui的datagrid提供了灵活的功能,最近有网上的朋友问我一个问题:“在datagird允许多选的情况下,只想让最后选中的一条高亮如何实现?”。
这种需求也是应用场景的,比如说两个表格A和B,B表格内容是通过A表格的行数据加载,这时A既要求可多选(默认选中项都会高亮),又要求能高亮出最后选中的行,矛盾就来了。
这种需求,想通过扩展而不改源码去实现是不太可能的,所以我们只能通过datagrid已经提供的接口去解决问题。本文正好也说一下官方文件没有开放的一个接口:
opt.finder.getTr(table,index,keyword,which);
该接口很实用,getSelected和getSelections等接口均用到了,该接口的四个参数含义分别如下:
Name | Type | Description |
---|---|---|
table | string | 表格的选择器 |
index | number | 行号 |
keyword | string | 用于区分查找哪些类型的行,可以为以下几个值: "body":查找整个行数据,一般同时会传入index; "footer":查找footer行数据,一般同时会传入index; "selected":查找被选中的行数据,不会传入index; "last":查找最后一条行数据,不会传入index; "allbody":查找整个行数据,不会传入index; "allfooter":查找所有footer行数据,不会传入index; |
which | number | 当存在frozenColumns的时候,表格内容将有两部分组成,which可能有三个值: 0:递归查找,具体用途暂时没研究; 1:在frozenColumns所在的table容器里查找; 2:在columns所在的table容器里查找; |
弄清楚这个接口的用法后,结合onSelect和onUnselect事件,我们就可以很轻松实现单行高亮了。定义一个样式,无背景,前景色为白色动态添加到相关tr里面即可,同时需要及时删除该样式。
实现代码:
定义样式:
.select-noback{ background-image:none; background-color:transparent; color:#000; }
管理样式:
$('#tt').datagrid({ url: 'datagrid_data2.json', title: 'DataGrid - ContextMenu', width: 700, height: 'auto', fitColumns: true, nowrap: true, autoRowHeight: true, rowStyler: function(index, data){ return "height:50px"; }, frozenColumns: [[ {field: 'ck',checkbox: true}, {field: 'itemid',title: 'Item ID',width: 80} ]], columns: [[ {field: 'productid',title: 'Product ID',width: 120}, {field: 'listprice',title: 'List Price',width: 80,align: 'right'}, {field: 'unitcost',title: 'Unit Cost',width: 80,align: 'right'}, {field: 'attr1',title: 'Attribute',width: 250}, {field: 'status',title: 'Status',width: 60,align: 'center'} ]], onSelect: function(index, data){ var opt = $(this).datagrid("options"); var rows1 = opt.finder.getTr(this, "", "selected", 1); var rows2 = opt.finder.getTr(this, "", "selected", 2); if (rows1.length > 0) { $(rows1).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).removeClass("select-noback"); } else { $(this).addClass("select-noback"); } }); } if (rows2.length > 0) { $(rows2).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).removeClass("select-noback"); } else { $(this).addClass("select-noback"); } }); } }, onUnselect: function(index, data){ var opt = $(this).datagrid("options"); var rows1 = opt.finder.getTr(this, "", "allbody", 1); var rows2 = opt.finder.getTr(this, "", "allbody", 2); if (rows1.length > 0) { $(rows1).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).removeClass("select-noback"); } }); } if (rows2.length > 0) { $(rows2).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).removeClass("select-noback"); } }); } } });
效果演示:
http://www.easyui.info/easyui/demo/datagrid/060.html
更好的方案:
在上述的业务需求中,datagrid难于实现的根本原因其实在于没有区分开select和check,个人觉得select跟check应该完全独立开来:
- select最多就一项,即当前点击的row,点击row时并不选中row;
- check的rows只能通过复选框勾选的方式选中,并且样式要跟select区分开来
按照这个思路,我整理了更加符合业务需求的代码和demo,仅供大家参考,也欢迎大家提出更好的建议来。
定义样式区分select和check:
.datagrid-row-selected{ background:#d7ebf9 url('../../themes/default/images/ui-bg_glass_80_d7ebf9_1x400.png') repeat-x 50% 50%; color:#000; } .datagrid-row-click{ background:#3baae3 url('../../themes/default/images/ui-bg_glass_50_3baae3_1x400.png') repeat-x 50% 50%; color:#fff; }
重新绑定行单击事件:
$('#tt').datagrid({ width: 700, height: 'auto', fitColumns: true, nowrap: true, pagination: true, autoRowHeight: true, rowStyler: function(index, data){ return "height:25px"; }, onHeaderContextMenu: function(e, field){ e.preventDefault(); if (!$('#tmenu').length) { createColumnMenu(); } $('#tmenu').menu('show', { left: e.pageX, top: e.pageY }); }, onLoadSuccess: function(){ var that = this; function bindRowsEvent(){ var panel = $(that).datagrid('getPanel'); var rows = panel.find('tr[datagrid-row-index]'); var datas = $(that).datagrid("getData"); var opts = $(that).datagrid("options"); rows.each(function(i){ var rowIdx = parseInt($(this).attr("datagrid-row-index")); $(this).unbind('click').bind('click', function(e){ opts.onClickRow.call(that, rowIdx, datas.rows[rowIdx]); return false; }); }); rows.find('div.datagrid-cell-check input[type=checkbox]').unbind().bind('click', function(e){ var index = $(this).parent().parent().parent().attr('datagrid-row-index'); if ($(this).attr('checked')) { $(that).datagrid('selectRow', index); } else { $(that).datagrid('unselectRow', index); } e.stopPropagation(); }); } setTimeout(function(){ bindRowsEvent(); }, 10); }, onClickRow: function(index, data){ var opt = $(this).datagrid("options"); var rows1 = opt.finder.getTr(this, "", "allbody", 1); var rows2 = opt.finder.getTr(this, "", "allbody", 2); if (rows1.length > 0) { $(rows1).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).addClass("datagrid-row-click"); } else { $(this).removeClass("datagrid-row-click"); } }); } if (rows2.length > 0) { $(rows2).each(function(){ var tempIndex = parseInt($(this).attr("datagrid-row-index")); if (tempIndex == index) { $(this).addClass("datagrid-row-click"); } else { $(this).removeClass("datagrid-row-click"); } }); } //#qq是另外一个grid var opt2 = $("#qq").datagrid("options"); opt2.url = "061-" + data.no + ".json"; opt = $(this).datagrid("options"); $('#qq').datagrid("reload"); } });
效果演示:
http://www.easyui.info/easyui/demo/datagrid/061.html
2012-8-4更新:
随着jquery easyui1.3版本的诞生,本文讨论的需求变得极为简单,因为作者终于把selected和checked的概念在这个版本中区分开来了,并且提供了以下两个新属性:
Name | Type | Description | Default |
---|---|---|---|
checkOnSelect | boolean | 设置checkbox是否跟用户点击行的行为联动,如果为true的话,用户点击行的时候会自动checked/unchecked被点击的行;如果为false,用户点击行不会对checkbox有任何影响. | true |
selectOnCheck | boolean | 设置selected是否跟checkbox联动,如果为true的话,用户勾选或者取消勾选复选框的时候会自动select或者unselect被勾选的行;如果为false,用户勾选或者取消勾选checkbox的行为不会对select有任何影响. | true |
同时1.3版本还提供了几个关于checkbox的方法,用于获取被勾选的所有行:
Name | Parameter | Description |
---|---|---|
getChecked | none | 返回所有被勾选的行 |
checkAll | none | 勾选当前页所有行的checkbox |
uncheckAll | none | 取消勾选当前页所有被勾选的行 |
checkRow | index | 勾选索引为index的行 |
uncheckRow | index | 取消勾选索引为index的行 |
下面是设置checkOnSelect:true,selectOnCheck:true,同时区分checked和selected的背景图,我们来看一下效果:
http://www.easyui.info/easyui/demo/datagrid/065.html
参考http://www.trirand.com/blog/jqgrid/jqgrid.html 的muti select,jqgrid的做法:
点击行,其他行不被选中,当前行被选中,单击单个的checkbox或者单击全选时可以多选
checkOnSelect:true,
selectOnCheck:true,
onClickRow:function(rowIndex){
jQuery(‘#datagridtb’).datagrid(‘uncheckAll’);
jQuery(‘#datagridtb’).singleSelect = true;
jQuery(‘#datagridtb’).datagrid(‘selectRow’, rowIndex);
},
checkAll:function(){
jQuery(‘#datagridtb’).singleSelect = false;
}