Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jqGrid - rowObject inconsistencies?

The first page of results with a jqgrid rowObject returns expected data but then returns incomplete data for subsequent pages of results. Why?

First page of results: rowObject[3] will equal "2"

Subsequent pages of results: rowObject[3] will equal "undefined" and returning to the first page of results will also now equal "undefined".

More details and some code:

With jqGrid, if you want to implement a custom formatter you use a parameter called rowObject that contains the row data. So for instance, one row of rowObject could be something like:

["18", "133", "Betelguese", "3", "photo.jpg", "", "0", ""]

So my custom formatter uses some of this data to prepare a link as follows:

var newval = '<a href="/proj/' + rowObject[3] + '/images/' + imgval + '">' + imgval + '</a>';

and this gives me a url like:

<a href="/proj/3/images/photo.jpg">photo.jpg</a>

So far so good. My problem is that when I go to the next page of results in the jqgrid I lose some of this data and get:

<a href="/proj/undefined/images/photo.jpg">photo.jpg</a>

If I load the page with all of the results displayed everything works fine, however if I use paging, only the first page of results will have the correct value for rowObject[3] while every other result on subsequent pages will not have that rowObject value!

So why is rowObject containing the correct data on what is initially loaded into the grid and seeming to lose that data when the next page of grid results appears?

One thing I'm seeing in Firebug that I don't understand... when the page initially loads I get:

console.log(rowObject); 
["18", "133", "Betelguese", "3", "photo.jpg", "", "0", ""]

On the next page of results, where things stop working as I expect, I see

console.log(rowObject);
Object { photo_id="18", site_id="133", more...} 

Why the change? The first result is json so why am I now getting this Object?

like image 648
Lothar Avatar asked Dec 20 '10 00:12

Lothar


1 Answers

I suppose you use loadonce:true option. It is one from the option which bring many problem (mostly understanding problems). The separation between local and remote data was clear before the introducing in the version 3.7 of jqGrid the new local sorting, paging and filtering (searching) features. Starting with jqGrid version 3.7 the loadonce:true option allows you to have a mix between the remote data which you have at the first load and the local data which you have later. In another answer the close problem was already discussed. At the end of the loading process in case of the loadonce:true option usage the datatype of jqGrid will be changed to 'local'. After that many things works different.

I suggest you to use jQuery.isArray(rowObject) as a quick and effective way to determine whether you should access rowObject per integer index rowObject[3] (if you access remote data) or per named property rowObject.projectId.

You can see the whole local data with $("#list").jqGrid('getGridParam','data'), which returns the array of all local rowObject.

If the data which you need to access (rowObject[3]) are not saved in the jqGrid in some column then you will not be able to see the information in the rowObject. In the case you can use an additional hidden column for the data or save the data at the first load inside of loadComplete: function(data) { ... } in any external object. You can test that $("#list").jqGrid('getGridParam','datatype') is 'json' (or 'xml' depend on your server data) and if it true, you can save all data returned from the server which you need (from the 3-th column of the data array) in an external array of object. So you will be able to access the data later inside your custom formatter.

UPDATED: The problem is solved in free jqGrid fork of jqGrid. The custom formatter (and cellattr, rowattr) contains still rowObject parameter for compatibility reasons, but there are exist additional rowData properties where the parsed data are saved as named properties:

formatter: function (cellValue, options, rowObject) {
    // either rowObject[1] or rowObject.site_id,
    // but options.rowData.site_id works ALWAYS
}

One can use

cellattr: function (rowid, cellValue, rowObject, cm, item) {
    // either rowObject[1] or rowObject.site_id,
    // but item.site_id works ALWAYS
}

in cellattr.

like image 160
Oleg Avatar answered Oct 06 '22 00:10

Oleg