Reputation: 3694
I have following custom grid
I need to get rowObject
when user clicks the image in Serial column to show a dialog allowing user to select another serial from available list for that row and then send the selected serial back to server.
As the images on column 5 and 6 execute functions related to data in their column, I cannot combine all images to a single action column with edit and delete buttons thus this answer is not suitable for me.
Currently I'm using following method to find desired row and call my function with row data. This method is slow as it has to go through data in a for loop and find the matching record. I stripped out all unrelated code and here is the rest
var TerminalColNames = [
'id',
'Serial'
];
var TerminalColModel = [
{ name: 'id', width: '180px', formatter: TerminalID_Formatter},
{ name: 'serial', width: '160px', formatter: Formatter, sortable: false }
];
function TerminalID_Formatter(cellvalue, options, rowObject) {
return ' ' +
'<img src="pencil.png" onclick="return edit(\'' + cellvalue + '\')"> ' +
'<img src="bin.png" onclick="return delete(\'' + cellvalue + '\')"> ' +
cellvalue;
}
function Formatter(cellvalue, options, rowObject) {
return '<img src="link.png" onclick="return bind(\'' + rowObject.id + '\')"></a> ' + rowObject.serial.current;
}
function CreateGrid(TableElement, colNames, colModel, data) {
$(TableElement).jqGrid({
datatype: 'local',
data: data,
colNames: colNames,
colModel: colModel,
height: '150px',
//onSelectRow: function (id, status, e) {
// rowData = $(this).jqGrid("getLocalRow", id);
// return RowAction(rowData);
//}
});
}
$(function () {
CreateGrid('#TerminalGrid', TerminalColNames, TerminalColModel, data.terminals);
});
function RowAction(rowData) {
alert('Row Action:' + JSON.stringify(rowData));
}
function bind(id) {
for (i in data.terminals){
if (data.terminals[i].id == id){
return ProcessBind(data.terminals[i]);
}
}
return false;
}
function ProcessBind(rowObject){
if (rowObject.id)
alert('Bind:' + rowObject.serial.avail.length);
else
alert('Bind not found');
return true;
}
var data = {
"id": "1234",
"terminals": [
{
"id": "111111",
"serial": {
"current": "888888",
"avail": [
"444444",
"555555",
"666666"
]
}
},
{
"id": "777777",
"serial": {
"current": "333333",
"avail": [
"999999",
"000000",
]
}
},
//.....
]
//.....
}
I didn't use $(this).closest('tr').attr('id')
because I believe it is much slower as it has to go through DOM to find the id and then go through the JSON data to find the row data. It also needs key: true
to be set in id column.
Question
Is there a better method to get the record data? Or is there a jqGrid method to return rowIndex in JSON array?
EDIT I forget to mention that I'm using oleg's free jqgrid 4.15.2
Upvotes: 1
Views: 4650
Reputation: 221997
First of all I'd recommended you to make some minor fixes in your code:
width: '180px'
to width: 180
and the option height: '150px'
to height: 150
. The current code works, but it's misunderstandable because width: '180em'
will be interpreted as width: 180
(or 180px
), but height: '150em'
will really increase the height of the grid.CreateGrid
function for example be used only once inside of $(function () {...});
and var data
only inside of CreateGrid
then you should move the declaration of variables/functions inside of the corresponding scope.Now about your main question. Event parameter of beforeSelectRow
, onSelectRow
or onCellSelect
callbacks provides all information, which you need. target
property is the DOM element clicked inside of the grid. One can test its class
, tagName
, name
or other properties to verify that specific image/icon is clicked. One don't need to use onclick
attribute.
About the performance. It's important to understand that access of properties of DOM element (class
, tagName
, name
, parentElement
and so on) is very quickly. The time to access of the properties isn't depend on the total number of elements on the page. It makes the working of closest
, hasClass
and other functions very quickly. It's recommended way. The below code provides an example of accessing to the full row data:
onSelectRow: function (rowid, status, e) {
var $self = $(this), $target = $(e.target),
p = $self.jqGrid("getGridParam"),
rowData = $self.jqGrid("getLocalRow", rowid),
$td = $target.closest("tr.jqgrow>td"),
iCol = $td.length > 0 ? $td[0].cellIndex : -1,
cmName = iCol >= 0 ? p.colModel[iCol].name : "";
switch (cmName) {
case "id":
if ($target.hasClass("myedit")) {
alert("edit icon is clicked in the row with rowid=" + rowid);
} else if ($target.hasClass("mydelete")) {
alert("delete icon is clicked in the row with rowid=" + rowid);
}
break;
case "serial":
if ($target.hasClass("mylink")) {
alert("link icon is clicked in the row with rowid=" + rowid);
}
break;
default:
break;
}
alert("full row data:\n\n" + JSON.stringify(rowData));
// return RowAction(rowData);
}
See https://jsfiddle.net/OlegKi/dfra7snb/
Code snippet:
$(function () {
"use strict";
function CreateGrid(TableElement, colNames, colModel, data) {
$(TableElement).jqGrid({
datatype: 'local',
data: data,
colNames: colNames,
colModel: colModel,
iconSet: "fontAwesome",
onSelectRow: function (rowid, status, e) {
var $self = $(this), $target = $(e.target),
p = $self.jqGrid("getGridParam"),
rowData = $self.jqGrid("getLocalRow", rowid),
$td = $target.closest("tr.jqgrow>td"),
iCol = $td.length > 0 ? $td[0].cellIndex : -1,
cmName = iCol >= 0 ? p.colModel[iCol].name : "";
switch (cmName) {
case "id":
if ($target.hasClass("myedit")) {
alert("edit icon is clicked in the row with rowid=" + rowid);
} else if ($target.hasClass("mydelete")) {
alert("delete icon is clicked in the row with rowid=" + rowid);
}
break;
case "serial":
if ($target.hasClass("mylink")) {
alert("link icon is clicked in the row with rowid=" + rowid);
}
break;
default:
break;
}
alert("full row data:\n\n" + JSON.stringify(rowData));
// return RowAction(rowData);
},
height: 150
});
}
var TerminalColNames = [
'id',
'Serial'
];
function TerminalID_Formatter(cellvalue, options, rowObject) {
return '<span class="fa fa-pencil fa-lg myedit" aria-hidden="true"></span>' +
'<span class="fa fa-trash-o fa-lg mydelete" aria-hidden="true"></span>' +
cellvalue;
}
function Formatter(cellvalue, options, rowObject) {
return '<span class="fa fa-link fa-rotate-90 fa-lg mylink" aria-hidden="true"></span>' +
rowObject.serial.current;
}
var TerminalColModel = [
{ name: 'id', width: '180em', formatter: TerminalID_Formatter},
{ name: 'serial', width: 160, formatter: Formatter, sortable: false }
];
var data = {
"id": "1234",
"terminals": [
{
"id": "111111",
"serial": {
"current": "888888",
"avail": [
"444444",
"555555",
"666666"
]
}
},
{
"id": "777777",
"serial": {
"current": "333333",
"avail": [
"999999",
"000000",
]
}
},
//.....
]
//.....
};
CreateGrid('#TerminalGrid', TerminalColNames, TerminalColModel, data.terminals);
});
.myedit, .mydelete, .mylink {
margin: 0 0.25em;
}
.myedit {
color: green;
}
.mydelete {
color: red;
}
.mylink {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.2/css/ui.jqgrid.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.2/jquery.jqgrid.min.js"></script>
<table id="TerminalGrid"></table>
Upvotes: 2
Reputation: 3277
If I understand correct you can use the method getLocalRow( rowid ) in case you use the local data. This method return quick the rowdata by index when the rowid is know.
Another trick is to use the internal _index jqGrid parameter to obtain the index of the row by given row id.
var grid = $("#jqGrid")[0];
var rowid = "somerowid";
var rowIndex = grid.p._index[rowid];
var datarow = grid.p.data[rowIndex];
The method getLocaRow use similar approach.
In case the data is not local you can use getInd method
The methods here are used in Guriddo jqGrid. More on the methods can be found Guriddo Documentation
Upvotes: 1