jQuery - jqGrid - onSelectRow事件中的不良行为 [英] jQuery - jqGrid - undesired behavior in onSelectRow event
问题描述
我有一个以前的问题,有关每个按钮可用的按钮一行jqGrid,这将在行被选中时激活。在 @Oleg
的帮助下,我能够像我以为应该这样工作。
进一步测试但是,我已经确定了 onSelectRow
事件中的不良行为。我发现,如果我有一个3行的网格,我点击第2行(激活按钮),然后(没有点击第2行按钮)单击第3行(它停用第2行按钮和amp ;激活第3行按钮),再次改变主意点击行1或2(无关紧要),然后在 THAT 点,然后点击重新发送
(提交)按钮,什么发生的是所选行然后重新发送3次。
以下是昨天从1个重新发送点击的4行的时间戳。
2013-05-28 16:49:04.817
2013-05-28 16:49:04.653
2013-05-28 16:49:04.560
2013-05-28 16:49:04.467
我把一些日志记录在页面&确认它确实调用POST 4个单独的时间,每次点击网格中的一行。
以下部分包含我目前在jqGrid建立的大部分配置/设置。
colNames:[Destination,Message Text,Send Time,Message Action],
/ pre>
colModel:[
{name:Destination,index :Destination,width:col1width,align:left,xmlmap:Rowset> Row> Destination,sortable:false},
{name:MessageText,index:MessageText,width:col2width ,align:left,xmlmap:Rowset> Row> MessageText,sortable:false},
{name:SendTime,index:SendTime,width:col3width,align:center :date,formatoptions:{srcformat:ISO8601Long,newformat:Ymd H:i:s},xmlmap:Rowset> Row> SendTime,sortable:false},
{名称:msgAct,
width:col4width,
align:center,
formatter:function(){
return< input name ='resendMsg'style = 'height:25px; width:65px;'type ='submit'value ='重新发送'disabled ='disabled'/> +
< input name ='cancelMsg'style ='height:25px; width:55px;'type ='submit'value ='Cancel'disabled ='disabled'/>
}}
],
viewrecords:true,
caption:capMsg,
rownum:0,
height:100%,
width:gridwidth,
工具栏:[true,top],
pager:jQuery(#pager1),
sortname:SendTime,
hidegrid:false ,//隐藏网格折叠的能力
defaults:{
altrows:true,
recordtext:View {0} - {1} of {2},
emptyrecords :没有记录查看,
loadonce:true,
pgtext:{1}
}的页面{0},
以下是
onSelectRow
事件。onSelectRow:function(id){
var tr = $(this).jqGrid(getInd,id,true);
var gridRow = $(this).jqGrid(getRowData,id);
var srow = $(this).jqGrid(getGridParam,selrow);
//禁用所有resendMsg&在网格中的cancelMsg按钮
$(this).find(input [name = resendMsg])。attr(disabled,disabled);
$(this).find(input [name = cancelMsg])。attr(disabled,disabled);
//现在启用当前行的按钮
$(tr).find(input [name = resendMsg])。removeAttr(disabled);
$(tr).find(input [name = cancelMsg])。removeAttr(disabled);
// disable dropdowns& sendMsg提交按钮
//捕获取消按钮单击
$(tr).find(input [name = cancelMsg])。click(function(){
// disable all resendMsg & cancelMsg网格中的按钮
$(this).find(input [name = resendMsg])。attr(disabled,disabled);
$(this).find input [name = cancelMsg])。attr(disabled,disabled);
//启用下拉列表并清除选择,重新加载网格
ReloadGrid();
});
//抓住重发按钮点击
$(tr).find(input [name = resendMsg])。click(function(){
ReSendMessage(gridRow.Destination, gridRow.MessageText);
//禁用网格中的所有resendMsg& cancelMsg按钮
$(this).find(input [name = resendMsg])。attr(disabled,disabled );
$(this).find(input [name = cancelMsg])。attr(disabled,disabled);
//启用下拉列表,清除选择并退出
$(#myGrid)。jqGrid(resetSelection);
});
},
和剩余的jqGrid代码:
gridview:true,
xmlReader:{
root:Rowsets,
row:Row,
repeatitems:false,
id:SendTime
},
loadComplete:function(){
//增加行高
$(td .jqgrow)高度(40)。 //数据网格行
//每隔一行的交替背景
$(tr.jqgrow:odd)。css({background-color:#DDDDDC,background-image : 没有});
$(th.ui-th-column)。css(font-weight,bold);
}
});
这就像onSelectRow事件正在累积点击次数然后调用click事件的功能,但是多次选择一行,但没有点击一个按钮。
我已经测试过,如果我点击一行,然后点击任一提交按钮,它按预期进行处理(
重新发送
提交第1行,并且取消
清除选择,而不执行任何操作。
我不知道是否可以,但是如果一行的已经选中您可以清除以前的选择(或重置它)以防止$ code> onSelectRow (以及按钮的点击事件)多次触发?
感谢任何关于如何解决此问题的想法,意见或建议。
编辑
包含
beforeSelectRow
如下面的回复中所述。$(#myGrid)bind(jqGridBeforeSelectRow ,function(e,id,eventOriginal){
var gsr = $(#myGrid)。jqGrid(getGridParam,selrow);
console.log(**** beforeSelectRow - (before if)lastSel =+ lastSel +id =+ id +gsr =+ gsr);
if(id&& id!== lastSel){
console。 log(id&& id!== lastSel);
console.log(id =+ id +lastSel =+ lastSel);
};
if (id!== lastSel){
if(lastSel == -1){//第一次通过
lastSel = id;
console.log(**** beforeSelectRow - first time thru - new val =+ lastSel +gsr =+ gsr);
return true;
}
else {
console.log(**** beforeSelectRow - lastSel - + last Sel + id =+ id +gsr =+ gsr);
return false;
}
}
else {
console.log beforeSelectRow - 否则匹配 - lastSel =+ lastSel +id =+ id +gsr =+ gsr);
return true;
}
});
将
.click
事件从onSelectRow
到loadComplete
(对于取消按钮作为测试),我尝试了上面的代码,网格。它执行的方式相同。
问题是
取消
按钮应该重置选择$(#myGrid)。resetSelection();
并重新加载网格。代码执行&不给出错误,但下一次beforeSelectRow
触发(当网格重新加载时),该ID仍然与当beforeSelectRow
和onSelectRow
当我点击行时触发,这意味着我不能选择一个新的行,直到整个页面被重新加载。仅当页面加载时,beforeSelectRow
不触发。
编辑
以下是取消按钮的代码,现在是位于
loadComplete
事件内。//抓取取消按钮点击
$(this).find(input [name = cancelMsg] ).click(function(){
//禁用网格中的所有resendMsg& cancelMsg按钮
$(this).find(input [name = resendMsg])。attr(disabled ,disabled);
$(this).find(input [name = cancelMsg])。attr(disabled,disabled);
//启用下拉列表和清除(reloadGrid);
lastSel = -1;
$(#myGrid)。 ;
解决方案绑定按钮(使用
.click
)里面的onSelectRow
回调。
而不是你可以通过在
loadComplete
中注册click
事件处理程序来移动代码,您可以从onSelectRow
toloadComplete
并将$(tr)
替换为$(this)
to搜索网格的所有按钮,而不仅仅是所选行的按钮。您仍然可以在onSelectRow
回调之前设置或删除禁用
属性。
更好的是让每一个按钮不要单独绑定。可以使用
onCellSelect
或beforeSelectRow
,这将从点击
处理器绑定在整个网格上。请参阅答案和这一个的代码示例。
更新:我不知道我是否正确理解您的问题,但我希望演示将演示该问题的解决方案。我没有使用任何明确的
点击
处理程序。最重要的更改(如果使用Internet Explorer可能很重要)将$ code> class ='cbox'添加到格式化程序以防止return
在行的jqGrid代码。代码中最重要的部分是colModel:[
{name:text,width:500 },
{name:msgAct,width:150,
formatter:function(){
return< input name ='resendMsg'class ='cbox'style ='height :25px; width:65px;'type ='submit'value ='重新发送'disabled ='disabled'/> +
< input name ='cancelMsg'class ='cbox'style ='height:25px; width:55px;'type ='submit'value ='Cancel'disabled ='disabled'/>
}}
],
onSelectRow:function(rowid){
var tr = $(this).jqGrid(getInd,rowid,true);
$(this).find(input [name = resendMsg],input [name = cancelMsg])。attr(disabled,disabled);
$(tr).find(input [name = resendMsg],input [name = cancelMsg])removeAttr(disabled);
},
beforeSelectRow:function(rowid,e){
var $ self = $(this),
$ td = $(e.target).closest(td ),
iCol = $ .jgrid.getCellIndex($ td [0]),
name = $(e.target).attr(name);
if(this.p.colModel [iCol] .name ===msgAct){
if(name ===resendMsg){
alert('Re-Send '按钮在行中= id =+ rowid +
\\\
text在行= \+ $ self.jqGrid(getCell,rowid,text)+\ );
} else if(name ===cancelMsg){
alert('取消'按钮在id =+ rowid)中单击;
setTimeout(function(){
$ self.trigger(reloadGrid);
},50);
}
}
返回true;
}
您可以在
beforeSelectRow
您需要的操作。I had a previous question regarding having buttons available in each row of a jqGrid, that would activate when the row was selected. With help from
@Oleg
I was able to get it to work like I thought it should.In further testing however, I have identified undesired behavior in that
onSelectRow
event. What I found was that if I have a grid with 3 rows in it, and I click on row 2 (which activates the buttons), then (without clicking on the row 2 buttons) click on row 3 (which deactivates row 2 buttons & activates row 3 buttons), and change my mind again & click row 1 or 2 (doesn't matter), and at THAT point then click the"Re-Send"
(submit) button, what happens is that the selected row is then re-sent 3 separate times.Following are the timestamps from 4 rows that were written from 1 "Re-Send" click yesterday.
2013-05-28 16:49:04.817 2013-05-28 16:49:04.653 2013-05-28 16:49:04.560 2013-05-28 16:49:04.467
I put some logging in the page & confirmed that it does call the POST 4 separate times, once for each click on a row in the grid.
The following sections contain most of the configuration/settings I currently have where the jqGrid gets built.
colNames: ["Destination", "Message Text", "Send Time","Message Action"], colModel:[ {name:"Destination",index:"Destination",width:col1width,align:"left", xmlmap:"Rowset>Row>Destination",sortable:false}, {name:"MessageText",index:"MessageText",width:col2width,align:"left",xmlmap:"Rowset>Row>MessageText",sortable:false}, {name:"SendTime",index:"SendTime",width:col3width,align:"center",formatter:"date",formatoptions: {"srcformat":"ISO8601Long", "newformat":"Y-m-d H:i:s"},xmlmap:"Rowset>Row>SendTime",sortable:false}, {name: "msgAct", width: col4width, align: "center", formatter: function() { return "<input name='resendMsg' style='height:25px;width:65px;' type='submit' value='Re-Send' disabled='disabled' />" + "<input name='cancelMsg' style='height:25px;width:55px;' type='submit' value='Cancel' disabled='disabled' />" }} ], viewrecords: true, caption: capMsg, rownum: 0, height: "100%", width: gridwidth, toolbar: [true, "top"], pager: jQuery("#pager1"), sortname: "SendTime", hidegrid: false, // hides the ability to collapse grid defaults: { altrows: true, recordtext: "View {0} - {1} of {2}", emptyrecords: "No records to view", loadonce: true, pgtext: "Page {0} of {1}" },
Following is the
onSelectRow
event.onSelectRow: function(id) { var tr = $(this).jqGrid("getInd",id,true); var gridRow = $(this).jqGrid("getRowData",id); var srow = $(this).jqGrid("getGridParam","selrow"); // disable all resendMsg & cancelMsg buttons in the grid $(this).find("input[name=resendMsg]").attr("disabled","disabled"); $(this).find("input[name=cancelMsg]").attr("disabled", "disabled"); // now enable the buttons for the current row only $(tr).find("input[name=resendMsg]").removeAttr("disabled"); $(tr).find("input[name=cancelMsg]").removeAttr("disabled"); // disable dropdowns & sendMsg submit button // catch the Cancel button click $(tr).find("input[name=cancelMsg]").click(function() { // disable all resendMsg & cancelMsg buttons in the grid $(this).find("input[name=resendMsg]").attr("disabled","disabled"); $(this).find("input[name=cancelMsg]").attr("disabled", "disabled"); // enable the dropdowns & clear the selection, reload grid ReloadGrid(); }); // catch the Re-Send button click $(tr).find("input[name=resendMsg]").click(function() { ReSendMessage(gridRow.Destination, gridRow.MessageText); // disable all resendMsg & cancelMsg buttons in the grid $(this).find("input[name=resendMsg]").attr("disabled","disabled"); $(this).find("input[name=cancelMsg]").attr("disabled", "disabled"); // enable the dropdowns, clear the selection and exit $("#myGrid").jqGrid("resetSelection"); }); },
and the remainder of the jqGrid code:
gridview: true, xmlReader: { root: "Rowsets", row: "Row", repeatitems: false, id: "SendTime" }, loadComplete: function() { // increase row height $("td",".jqgrow").height(40); // data grid rows // alternate background of every other row $("tr.jqgrow:odd").css({"background-color": "#DDDDDC", "background-image": "none"}); $("th.ui-th-column").css("font-weight","bold"); } });
It's like the onSelectRow event is accumulating the number of clicks & then calling the click event's functions however many times a row was selected but a button wasn't clicked.
I have tested though, that if I click on a row, and then click on either of the submit buttons, that it processes as expected (a "
Re-Send
" submits the row 1 time, and a "Cancel
" clears the selection & does nothing else).I don't know if it is possible, but can you prevent a subsequent
onSelectRow
from firing if a row's already selected? Can you clear the previous selection (or reset it) to prevent theonSelectRow
(and the click event for the button) from firing multiple times?I'd appreciate any thoughts, comments or suggestions as to how to fix this behavior.
EDIT
Including the code for
beforeSelectRow
as noted in a response below.$("#myGrid").bind("jqGridBeforeSelectRow", function(e, id, eventOriginal) { var gsr = $("#myGrid").jqGrid("getGridParam","selrow"); console.log(" **** beforeSelectRow - (before if) lastSel = " + lastSel + " id = " + id + " gsr = " + gsr); if (id && id !== lastSel) { console.log("id && id !== lastSel"); console.log(" id = " + id + " lastSel = " + lastSel); }; if (id !== lastSel) { if (lastSel == -1) { // first time thru lastSel = id; console.log(" **** beforeSelectRow - first time thru - new val = " + lastSel + " gsr = " + gsr); return true; } else { console.log(" **** beforeSelectRow - lastSel - " + lastSel + " <> id = " +id + " gsr = " + gsr); return false; } } else { console.log(" **** beforeSelectRow - otherwise they matched - lastSel = " + lastSel + " id = " + id + " gsr = " + gsr); return true; } });
After moving the
.click
event from theonSelectRow
into theloadComplete
(for the Cancel button as a test), I tried the above code both inside & outside the code for the grid. It performs the same either way.The issue is that the
Cancel
button is supposed to reset the selection$("#myGrid").resetSelection();
and reload the grid. The code executes & doesn't give an error, but the very next timebeforeSelectRow
fires (when the grid is reloaded), the id is still the same as it was whenbeforeSelectRow
andonSelectRow
fired when I clicked on the row, which means that I can never select a new row until the entire page is reloaded. Only on page load is whenbeforeSelectRow
doesn't fire.EDIT
Following is the code for the Cancel button, which is now located inside the
loadComplete
event.// catch the Cancel button click $(this).find("input[name=cancelMsg]").click(function() { // disable all resendMsg & cancelMsg buttons in the grid $(this).find("input[name=resendMsg]").attr("disabled","disabled"); $(this).find("input[name=cancelMsg]").attr("disabled", "disabled"); // enable the dropdowns & clear the selection, reload grid console.log("ReloadGrid (inside Cancel function) "); lastSel = -1; $("#myGrid").trigger("reloadGrid");
解决方案It's wrong to bind button (to use
.click
) inside ofonSelectRow
callback.Instead of you can move the code with registering
click
event handler inside ofloadComplete
. You can just move the code fromonSelectRow
toloadComplete
and replace$(tr)
to$(this)
to search inside of all buttons of the grid and not only the buttons of selected row. You can still set or removedisabled
attribute inside ofonSelectRow
callback.More better would be to make no individual binding for every button. One can just use
onCellSelect
orbeforeSelectRow
which will be called fromclick
handler bound on whole grid. See the answer and this one for code examples.UPDATED: I am not sure that I understand correctly your problem, but I hope that the demo will demonstrate the solution of the problem. I don't used any explicit
click
handler. The most important change (which could important if you use Internet Explorer) is addingclass='cbox'
to the formatter to preventreturn
in the line of jqGrid code. The most important part of the code is belowcolModel: [ { name: "text", width: 500 }, { name: "msgAct", width: 150, formatter: function () { return "<input name='resendMsg' class='cbox' style='height:25px;width:65px;' type='submit' value='Re-Send' disabled='disabled'/>" + "<input name='cancelMsg' class='cbox' style='height:25px;width:55px;' type='submit' value='Cancel' disabled='disabled'/>" }} ], onSelectRow: function (rowid) { var tr = $(this).jqGrid("getInd", rowid, true); $(this).find("input[name=resendMsg],input[name=cancelMsg]").attr("disabled", "disabled"); $(tr).find("input[name=resendMsg],input[name=cancelMsg]").removeAttr("disabled"); }, beforeSelectRow: function (rowid, e) { var $self = $(this), $td = $(e.target).closest("td"), iCol = $.jgrid.getCellIndex($td[0]), name = $(e.target).attr("name"); if (this.p.colModel[iCol].name === "msgAct") { if (name === "resendMsg") { alert("'Re-Send' button clicked in the row with id=" + rowid + "\ntext in the row =\"" + $self.jqGrid("getCell", rowid, "text") + "\""); } else if (name === "cancelMsg") { alert("'Cancel' button clicked in the row with id=" + rowid); setTimeout(function () { $self.trigger("reloadGrid"); }, 50); } } return true; }
You can replace alerts inside of
beforeSelectRow
to the action which you need.这篇关于jQuery - jqGrid - onSelectRow事件中的不良行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!