jqGrid 在编辑时访问单元格数据

IT技术 javascript jquery jqgrid
2021-02-05 12:46:06

我目前正在使用afterSaveCell手动更新网格中的某些单元格。如果用户使用 enter 来保存当前编辑的单元格,我就可以正常工作。

不幸的是,如果他们单击或跳出单元格,他们将直接编辑到另一个单元格中,我将无法再获取新编辑单元格的单元格值,因为getCell只会返回输入控件的 html。

总之,有没有办法在编辑时访问单元格的值?

jQuery(document).ready(function () {
    var mydata = [
        {id:"1", invdate:"2007-10-01",name:"test",  note:"note",  amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"2", invdate:"2007-10-02",name:"test2", note:"note2", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"3", invdate:"2007-09-01",name:"test3", note:"note3", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"4", invdate:"2007-10-04",name:"test",  note:"note4", amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"5", invdate:"2007-10-05",name:"test5", note:"note5", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"6", invdate:"2007-09-06",name:"test",  note:"note6", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"7", invdate:"2007-10-04",name:"test7", note:"note7", amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"8", invdate:"2007-10-03",name:"test8", note:"note8", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"9", invdate:"2007-09-01",name:"test",  note:"note9", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"10",invdate:"2007-09-08",name:"test10",note:"note10",amount:"500.00",tax:"30.00",total:"530.00"},
        {id:"11",invdate:"2007-09-08",name:"test11",note:"note11",amount:"500.00",tax:"30.00",total:"530.00"},
        {id:"12",invdate:"",name:"TOTAL",  note:"",amount:"",tax:"",total:""}
    ];

    var grid = $("#list");

    grid.jqGrid({
        cellsubmit: 'remote',
        cellurl: '/Example/GridSave',
        datatype: "local",
        data: mydata,
        mtype: 'POST',
        colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'],
        colModel: [
            { name: 'id', index: 'id', width: 65, sorttype: 'int', hidden: true },
            { name: 'invdate', index: 'invdate', width: 120, align: 'center', formatter: 'date', formatoptions: { newformat: 'd-M-Y' }, sortable: false },
            { name: 'name', index: 'name', editable: true, width: 90, sortable: false },
            { name: 'amount', index: 'amount', editable: true, width: 70, formatter: 'number', align: 'right', sortable: false },
            { name: 'tax', index: 'tax', editable: true, width: 60, formatter: 'number', align: 'right', sortable: false },
            { name: 'total', index: 'total', editable: true, width: 60, formatter: 'number', align: 'right', sortable: false },
            { name: 'note', index: 'note', width: 100, sortable: false }
        ],
        rowNum: 1000,
        pager: '#pager',
        viewrecords: true,
        sortorder: "desc",
        caption: "afterSaveCell Issue",
        height: "100%",
        cellEdit: true,
        gridComplete: function () {
            calculateTotal();
        },
        afterSaveCell: function (rowid, name, val, iRow, iCol) {
            calculateTotal();
        }
    });
});

function calculateTotal() {
    var totalAmount = 0;
    var totalTax = 0;

    var grid = jQuery("#list");

    var ids = grid.jqGrid('getDataIDs');
    for (var i = 0; i < ids.length; i++) {
        var id = ids[i];

        if (grid.jqGrid('getCell', id, 'name') === "TOTAL") {
            grid.jqGrid('setRowData', id, {
                'amount': totalAmount,
                'tax': totalTax,
                'total': totalAmount + totalTax
            });
        }
        else {
            totalAmount += Number(grid.jqGrid('getCell', id, 'amount'));
            totalTax += Number(grid.jqGrid('getCell', id, 'tax'));
        }
    }
}

提前致谢!

3个回答

我在您的代码中看到两个问题。第一个更美观,但正确的解决方案可以在未来简化很多事情。

第一个问题是您手动添加“TOTAL”行作为网格数据的一部分,并在calculateTotal函数内部计算行中的值更好的方法是使用footerrow:true选项,在网格底部添加不会与网格数据混合的附加行对于基于服务器的数据,您可以使用userdata来自服务器的部分 JSON 或 XML 响应,并userDataOnFooter:true另外使用userDatajqGrid 参数中的数据发送到页脚行。在“本地”数据类型的情况下,可以使用footerData方法设置(或获取)页脚中的数据。此外,可以使用getCol方法来计算列中元素的总和。所以你的calculateTotal函数版本可以改写为

var grid = $("#list");
var calculateTotal = function() {
    var totalAmount = grid.jqGrid('getCol','amount',false,'sum'),
        totalTax = grid.jqGrid('getCol','tax',false,'sum');
    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
}

现在到你的主要问题。您使用单元格编辑模式。如果函数calculateTotal(您的原始版本或我的简化版本)将在 'amount' 或 'tax' 单元格中的一个处于编辑模式时被调用,calculateTotal则将读取带有<input>元素的HTML 片段而不是带有数字和计算将失败。

我创建calculateTotal一个每秒调用一次的小演示因此,如果您单击“金额”或“税金”列中的任何单元格,您将看到在页脚中的第 0 行将显示为总和。所以这个演示和cellsubmit:'clientArray'你的原始代码有同样的问题cellsubmit:'remote'

为了解决这个问题,可以data在总和计算过程中使用jqGrid 的参数:

var grid = $("#list");
var calculateTotal = function() {
    var gridData = grid.jqGrid('getGridParam','data'),
        i=0,totalAmount=0,totalTax=0;
    for (;i<gridData.length;i++) {
        var rowData = gridData[i];
        totalAmount += Number(rowData.amount);
        totalTax += Number(rowData.tax);
    }
    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
}

您将在此处找到相应的固定演示在您的最终代码中,您可以删除

setInterval(calculateTotal, 1000);

我仅用于演示目的,仅在afterSaveCell事件处理程序中刷新页脚

更新:如果您使用远程数据,则不能使用data参数。因此,<input>如果需要,必须元素中获取数据我又创建了一个演示来演示如何做到这一点。的代码calculateTotal会更长:

var getColumnIndexByName = function(grid,columnName) {
    var cm = grid.jqGrid('getGridParam','colModel');
    for (var i=0,l=cm.length; i<l; i++) {
        if (cm[i].name===columnName) {
            return i; // return the index
        }
    }
    return -1;
},
getTextFromCell = function(cellNode) {
    return cellNode.childNodes[0].nodeName === "INPUT"?
           cellNode.childNodes[0].value:
           cellNode.textContent || cellNode.innerText;
},
calculateTotal = function() {
    var totalAmount = 0, totalTax = 0,
        i=getColumnIndexByName(grid,'amount');
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",grid[0]).each(function() {
        totalAmount += Number(getTextFromCell(this));
    });

    i=getColumnIndexByName(grid,'tax');
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",grid[0]).each(function() {
        totalTax += Number(getTextFromCell(this));
    });

    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
};
@Oleg:很好的答案!我还有一个问题 - 我有Inisde我的行一个选择类型单元 - 我如何只有在选择值是它内部的第一个值时才总结总金额?我的意思是我想根据选择单元格内的值计算总和。谢谢..
2021-03-16 12:46:06
似乎jqGrid('getGridParam','data')唯一适用于本地数据。将它与我的远程 json 数据一起使用会返回一个空字符串。
2021-03-27 12:46:06
@user590586:您必须扩展getTextFromCell. 我真的不明白你想如何计算select元素的总和,因为select通常包含文本而不是整数。
2021-04-04 12:46:06
@Shawn:是的,这是正确的,但是您的演示使用了本地数据。如果您需要使用远程数据,您必须检查来自的数据是否getCell为 HTML 片段<input>您可以使用我描述的更快速的 jQuery 方式,而不是通过行 id 的枚举stackoverflow.com/questions/5010761/...为了让您更轻松,我创建了另一个演示ok-soft-gmbh.com/jqGrid/CellEditAfterSaveCellProblem1.htm,它可以满足您的需求。
2021-04-07 12:46:06
@Oleg:金额不在选择单元格中,它在另一个单元格中。我想要做的是仅当我在选择单元格中有特定值时才对这个数量求和。你明白我在做什么吗?是否可以?
2021-04-07 12:46:06

感谢 oleg 对我的解决方案是应用和更改您放置的内容

var ListTabla="ListFormatos";
var request="../../tabla_general/tabla_general_mantenimiento.php";

var getColumnIndexByName = function(grid,columnName) {
var cm = $("#"+grid).jqGrid('getGridParam','colModel');
for (var i=0,l=cm.length; i<l; i++) {
    if (cm[i].name===columnName) {
        return i; // return the index
    }
}
return -1;
},

getTextFromCell = function(cellNode) {
return cellNode.childNodes[0].nodeName === "INPUT"?
       cellNode.childNodes[0].value:
       cellNode.textContent || cellNode.innerText;
},

calculateTotal = function(grid) {   

total_hpr_suebas = retorna_suma('hpr_suebas',grid);
total_hpr_asifam = retorna_suma('hpr_asifam',grid);
total_hpr_bashpr = retorna_suma('hpr_bashpr',grid);
total_hpr_remcom = retorna_suma('hpr_remcom',grid);
total_hpr_basmes = retorna_suma('hpr_basmes',grid);
total_hpr_provcts = retorna_suma('hpr_provcts',grid);
total_hpr_provgrat = retorna_suma('hpr_provgrat',grid);
total_hpr_provvac=retorna_suma('hpr_provvac',grid);

    $("#"+grid).jqGrid('footerData','set',{sec_detsec:'TOTAL',hpr_suebas:total_hpr_suebas,hpr_asifam:total_hpr_asifam,hpr_bashpr:total_hpr_bashpr,hpr_remcom:total_hpr_remcom,hpr_basmes:total_hpr_basmes,hpr_provcts:total_hpr_provcts,hpr_provgrat:total_hpr_provgrat,hpr_provvac:total_hpr_provvac});
};

retorna_suma=function(campo,grid)
{
    total=0;
    i=getColumnIndexByName(grid,campo);
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",$("#"+grid)[0]).each(function() {
        total+= Number(getTextFromCell(this));
    });
    return total;
}

function fn_jqgrid_history_provisiones_trabajador(tra_idtra,fecha_inicio,fecha_fin)
{
    jQuery("#"+ListTabla).jqGrid({
                    url:request+"?action=search_history_provisiones_trabajador&tra_idtra="+tra_idtra+"&fecha_inicio="+fecha_inicio+"&fecha_fin="+fecha_fin,
                    async: false,
                    datatype: 'json',
                    colNames:['','ID','SECTOR','BASICO','ASIG. FAM','DIAS','BASE','REM. COMP.','BASE MES','P.CTS','P.GRAT.','P.VAC.','MES','ANIO','PORC.','SAL.VAC.','SAL.GRAT.'],
                    colModel:[
                         {name:'act', index:'act', width:50, resizable:true, align:"center",hidden:true},
                        {name:'id', index:'id', width:50, resizable:true, align:"center",hidden:true},
                        {name:'sec_detsec', index:'sec_detsec', width:80},
                        {name:'hpr_suebas', index:'hpr_suebas', width:60},
                        {name:'hpr_asifam', index:'hpr_asifam', width:50},
                        {name:'hpr_numdia', index:'hpr_numdia', width:30},
                        {name:'hpr_bashpr',index:'hpr_bashpr', width:60},
                        {name:'hpr_remcom,',index:'hpr_remcom', width:60},
                        {name:'hpr_basmes', index:'hpr_basmes', width:60},
                        {name:'hpr_provcts', index:'hpr_provcts', width:60},
                        {name:'hpr_provgrat', index:'hpr_provgrat', width:60},
                        {name:'hpr_provvac', index:'hpr_provvac', width:60},
                        {name:'hpr_meshpr', index:'hpr_meshpr', width:30},
                        {name:'hpr_aniohpr,',index:'hpr_aniohpr', width:30},
                        {name:'hpr_salpor', index:'hpr_salpor', width:50},
                        {name:'hpr_salval_vac', index:'hpr_salval_vac', width:50},
                        {name:'hpr_salval_grat', index:'hpr_salval_grat', width:50}
                    ],
                    pager: '#paginacion',
                    rowNum:10,
                    rowList:[10,20,30],
                    sortname: 'ID',
                    ondblClickRow:function(rowid, iRow, iCol, e)
                    {
                                obj=jQuery("#"+ListTabla).jqGrid('getRowData',rowid);
                    }
                    ,
                    sortorder: 'desc',
                    editurl:request,
                    viewrecords: true,
                    caption: 'Provisiones',
                    //rownumbers: true,
                     height: 250,
                    rowheight: 280,
                    footerrow : true,
                    gridComplete: function () {
                        calculateTotal(ListTabla);
                },
                    afterSaveCell: function (rowid, name, val, iRow, iCol) {
                        //calculateTotal(ListTabla);
                    }
                    }).navGrid('#paginacion',{add:false,edit:false, del:false});

                        jQuery("#"+ListTabla).jqGrid('bindKeys', {"onEnter":function( rowid ) {
                                                                    obj=jQuery("#"+ListTabla).jqGrid('getRowData',rowid);
                                                                    } } );  

                 }

如果您只想重新计算总数,您可以在 afterSaveCell 事件中使用触发器重新加载网格。像这样:

afterSaveCell: function (rowid, name, val, iRow, iCol) 

        {
          jQuery("#list11").jqGrid('setGridParam',{datatype:'local',loadonce:true}).trigger('reloadGrid');
        }