javascript jqGrid 在编辑时访问单元格数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5121350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jqGrid access cell data while it is being edited
提问by Shawn
I'm currently using afterSaveCellto handle manually updating some cells in a grid. I have this working fine if the user uses enter to save the currently editing cell.
我目前正在使用afterSaveCell手动更新网格中的某些单元格。如果用户使用 enter 来保存当前编辑的单元格,我就可以正常工作。
Unfortunately, if they click or tab out of the cell they are editing directly into another cell I can no longer grab the cell value of the newly edited cell as getCellwill only return the html for the input control.
不幸的是,如果他们单击或跳出单元格,他们将直接编辑到另一个单元格中,我将无法再获取新编辑单元格的单元格值,因为getCell只会返回输入控件的 html。
In summary, is there any way to access the value of the cell even while it is being edited?
总之,有没有办法在编辑时访问单元格的值?
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'));
}
}
}
Thanks in advance!
提前致谢!
回答by Oleg
I see two problems in your code. The first one is more cosmetic, but the correct solution can simplify many things in the future.
我在您的代码中看到两个问题。第一个更美观,但正确的解决方案可以在未来简化很多事情。
The first problem is that you add manual the "TOTAL" row as a part of grid data and calculate the values in the row inside calculateTotalfunction. The better way is to use footerrow:trueoption, which add additional row at the bottom of grid which will be not mixedwith the grid data. For server based data you can use userdatapart of JSON or XML response from the server and use userDataOnFooter:trueadditionally to till the data from the userDatajqGrid parameter to the footer row. In case of "local" datatype one can use footerDatamethod to set (or get) the data in the footer. Additionally the method getColcan be used co calculate the sum of elements in the column. So your version of calculateTotalfunction can be rewritten as
第一个问题是您手动添加“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});
}
Now to your main problem. You use cell edit mode. If the function calculateTotal(your original or my simplified version) will be called at the time when one from the cells of the 'amount' or 'tax' are in the editing mode, the calculateTotalwill be read HTML fragment with <input>element instead of the string with the number and the calculation will failed.
现在到你的主要问题。您使用单元格编辑模式。如果函数calculateTotal(您的原始版本或我的简化版本)将在 'amount' 或 'tax' 的单元格中的一个处于编辑模式时被调用,calculateTotal则将读取带有<input>元素的HTML 片段而不是带有的字符串数字和计算将失败。
I created the small demowhich call calculateTotalevery second. So if you click on any cell from the
'amount' or 'tax' column you will see that in the footer row 0 will be displayed as the sum. So the demo having cellsubmit:'clientArray'has the same problem as in your original code with cellsubmit:'remote'.
我创建了calculateTotal一个每秒调用一次的小演示。因此,如果您单击“金额”或“税金”列中的任何单元格,您将看到在页脚中的第 0 行将显示为总和。所以这个演示和cellsubmit:'clientArray'你的原始代码有同样的问题cellsubmit:'remote'。
To solve the problem one can use dataparameter of jqGrid during the sum calculation:
为了解决这个问题,可以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});
}
The corresponding fixed demo you will find here. In your final code you can remove
您将在此处找到相应的固定演示。在您的最终代码中,您可以删除
setInterval(calculateTotal, 1000);
which I used for demonstration purpose only and refresh the footer in the afterSaveCellevent handler only.
我仅用于演示目的,仅在afterSaveCell事件处理程序中刷新页脚。
UPDATED: If you work with remote data you can not use dataparameter. So one have to get data from the <input>element if needed. I created one more demowhich demonstrate how one can do this. The code of calculateTotalwill be longer:
更新:如果您使用远程数据,则不能使用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});
};
回答by user1413147
Thanks oleg the solution for me was applying and changing what you put
感谢 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);
} } );
}
回答by Julia
If you just want to recalculate total number, you can use trigger to reload the grid in afterSaveCell event. Like this:
如果您只想重新计算总数,您可以在 afterSaveCell 事件中使用触发器重新加载网格。像这样:
afterSaveCell: function (rowid, name, val, iRow, iCol)
{
jQuery("#list11").jqGrid('setGridParam',{datatype:'local',loadonce:true}).trigger('reloadGrid');
}

