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");
.click
into theloadComplete
helped to have it get called only once. However, I've noticed that therowID
is still the value it was, and isn't resetting, even though I am calling$("#myGrid").ResetSelection();
from inside the.click
event handler that's moved into theloadComplete
. That means that if I have 3 rows displayed & select row 3, then hit the cancel button on the row, thebeforeSelectRow
still has row 3's id in it & unless I reload the page, I can never select any other row until the page is reloaded. I have included thebeforeSelectRow
code above. – Sapodilla