jQuery - jqGrid - onSelectRow事件中的不良行为 [英] jQuery - jqGrid - undesired behavior in onSelectRow event

查看:4864
本文介绍了jQuery - jqGrid - onSelectRow事件中的不良行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个以前的问题,有关每个按钮可用的按钮一行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],
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},
/ pre>

以下是 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 to loadComplete 并将 $(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 the onSelectRow (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 the onSelectRow into the loadComplete (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 time beforeSelectRow fires (when the grid is reloaded), the id is still the same as it was when beforeSelectRow and onSelectRow 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 when beforeSelectRow 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 of onSelectRow callback.

Instead of you can move the code with registering click event handler inside of loadComplete. You can just move the code from onSelectRow to loadComplete 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 remove disabled attribute inside of onSelectRow callback.

More better would be to make no individual binding for every button. One can just use onCellSelect or beforeSelectRow which will be called from click 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 adding class='cbox' to the formatter to prevent return in the line of jqGrid code. The most important part of the code is below

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='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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆