现在的位置: 首页 > easyui > Grid > datagrid > 正文
实现datagrid多选情况下单行高亮
2012年06月16日 datagrid ⁄ 共 6086字 评论数 2 ⁄ 被围观 21,056 views+
文章目录
[隐藏]

数据表格组件是大家最常用的组件之一,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

目前有 2 条留言 其中:访客:1 条, 博主:0 条 引用: 1

  1. billxia : 2012年12月18日02:08:37  -49楼 @回复 回复

    参考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;
    }

给我留言

留言无头像?


×