JQGrid 'undefined' error - jqgrid

I am getting a JavaScript error when trying to use the JQGrid:
"Message: 'undefined' is null or not an object"
When I debug on my server, I see that my JSON output looks like this: (does it matter that the "id" value is not inside double quotes?)
{
"page":"1",
"total":"20",
"records":"5",
"rows":[
{"id":1,"name":"Sam","phone":"732-333-2222"},
{"id":2,"name":"Dan","phone":"000-222-1111"},
{"id":6,"name":"George","phone":"333333"},
{"id":4,"name":"Jerry","phone":"332-333-4444"},
{"id":7,"name":"John","phone":"666666"},
{"id":8,"name":"Tom","phone":"3333"}]
}
.. and my page looks like this:
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#list").jqGrid({
url:'/myUrlPage',
datatype: 'json',
mtype: 'GET',
colNames:['Id', 'Name', 'Phone'],
colModel :[
{name:'id', index:'id', width:55},
{name:'name', index:'name', width:90},
{name:'phone', index:'phone', width:150, sortable:false} ],
pager: jQuery('#pager'),
rowNum:10, rowList:[10,20,30],
sortname: 'id',
sortorder: "desc",
viewrecords: true,
imgpath: 'themes/basic/images',
caption: 'My first grid' }); });
</script>

You main problem will be solved if you include
jsonReader: { repeatitems: false }
parameter in your jqGrid. See details in the jqGrid documentation.
Moreover I modified a little your demo. You can see it here. I recommend you remove deprecated imgpath parameter. Instead of that I recommend you to use height: 'auto' which gives you good results in the most cases. Instead of jQuery('#pager') is better to use just '#pager'. You should additionally increase the value of the width for some columns in case of the usage of pager and viewrecords: true. I included in my demo the jQuery("#pager_left").hide(); statement which hide some block of the pager which you not use now. If you will start to use navigator buttons you should remove the line.
One more remarks about the JSON data which you use. The values of id, page, total and records properties can be either strings or integers, so "id":1 will gives you the same results as "id":"1".
It's important to understand how you should fill page, total and records. You current values are page=1, total=20, records=5 and you data contain 6 rows. All the data has no sense. The jqgrid asked the server with respect of additional parameters which it appended to the URL to gives one page of the data with 10 rows per page (rowNum:10). Your answer from the server means that your data contain 5 items (records=5) totally. If you order the data (the 5 items) in pages (10 items per page) you will have 20 pages (total=20) and the first one from there (page=1) you are filled with the data (6 items). The strange values of page, total and records from your JSON data follows to strange values in the pager on the demo:
I would recommend you to read the answer where I tried to describe why jqGrid need so strange format of JSON data.

Related

free jqgrid custom formatter lost after sorting or filtering

I am using free jqgrid 4.13.0
I wrote a custom formatter, but unfortunately my cell contents of that column are always lost after sorting the table or filtering. I am probably doing something wrong in the formatter function, but haven't really understood what is missing. Anyone can spot my mistake? Why is it working fine with the built in ones, but not with mine. I got inspired by this one: http://www.ok-soft-gmbh.com/jqGrid/CascadingFormater.htm
I can see how the example is calling $.fn.fmatter.call and maybe I need to do this too. Is this the key? Unfortunately I can't find any documentation on how to do this if I write the function myself.
This is my setup:
var formatEnduser = function (cellValue, options, rowObject, action){
return rowObject.so_enduser_id == undefined ? '' : ''+rowObject.so_enduser_name+'';
}
$("#jqGrid").jqGrid({
datatype: "jsonstring",
datastr: jsonData,
jsonReader: {
root: 'rows',
id: 'crmentity_id',
repeatitems: false,
page: function(obj) { return 1; },
total: function(obj) { return 1; },
records: function(obj) { return obj.rows.length; },
},
autowidth: true,
height: 600,
shrinkToFit: true,
rownumbers: true,
rowNum: 5,
pager: false,
loadonce: true,
viewrecords: true,
colModel: [
{
name: 'crmentity_id',
key: true,
hidden: true
},
{
label: 'Enduser',
name: 'so_enduser_name',
searchoptions: {
sopt : ['cn']
},
formatter: formatEnduser
},
]
});
$('#jqGrid').jqGrid('filterToolbar');
The object jsonData looks like this:
Object { rows=[623], so_total_total=4321, in_total_total=1234 }
In the property rows can be found this:
[Object { crmentity_id="60199", so_enduser_id="6808", so_enduser_name="enduser123", mehr...}, Object { crmentity_id="60136", so_enduser_id="6362", so_enduser_name="userend321", mehr...}, 620 mehr...]
Thanks a lot for any help!
EDIT: I added a jsfiddle to demonstrate the problem, search for end in the filter and see how the data disappears. Sorting does the same. http://jsfiddle.net/tztj9yn7/2/
The main problem is your code is the following. You use datatype: "jsonstring" and the custom formatter uses the property so_enduser_id of the input data, but the property is not a column of the grid. The datatype "jsonstring" will be processed in the same way like the datatype "json" (or "jsonp" or "xml"). It will be read by jqGrid and saved locally only the columns from colModel and jsonReader.id additionally. Thus the property so_enduser_id of the input data will be available in rowObject only during initial reading of the grid. All what I wrote till now is the same for old jqGrid and for free jqGrid.
In case of usage old jqGrid there are two alternative ways to fix the problem:
add hidden column with name: "so_enduser_id"
replace datatype: "jsonstring", datastr: jsonData to datatype: "local", data: jsonData.rows and replace jsonReader to localReader: { id: 'crmentity_id' }. The input data will be saved with all properties (like it be in the input) in case of usage datatype: "local" and the problem will be fixed.
If you would need to load the data directly from the URL then the second way (datatype: "local") will be not possible and the only way will be the usage of hidden columns for all properties which you need later.
Free jqGrid provides you another very simple way: the usage of additionalProperties option. The idea of additionalProperties is very simple. One need sometimes to save some additional properties from every item of input data to use there locally later (because of usage of loadonce: true). Saving the data in DOM is much more expensive as saving the data in the JavaScript structures. One can just use the option like additionalProperties: ["crmentity_id", "so_enduser_id"] to inform free jqGrid to read some other properties and to save there locally. As the result your code will be fixed immediately: see http://jsfiddle.net/tztj9yn7/3/
One more important recommendation about the usage of custom formatters in free jqGrid. There are exist some important problem with the rowObject parameter. It's just the input item exactly like it be in the source. Thus if you would use datatype: "xml" for example then the rowObject parameter would be XML node. In the same way, if you would use repeatitems: true format (["60199", "6808", "enduser123"] instead of {crmentity_id:"60199", so_enduser_id:"6808", so_enduser_name:"enduser123"}) then you will have to use rowObject[1] instead of rowObject.so_enduser_id to access the property so_enduser_id from initial input data. On the next sorting or filtering you will have another format of rowObject (rowObject.so_enduser_id) because of the input data will be the data from the local data parameter. Free jqGrid still use the same format of rowObject parameter to provides the best compatibility with the old versions of jqGrid, but it set additionally rowData property of the options parameter. The options.rowData have always deterministic named format of data and one can use always options.rowData.so_enduser_id independent from the format of the input data and the datatype used. Thus options.rowData is preferred way to access input data. One should't use the third parameter at all. The resulting code of the formatter will be
var formatEnduser = function (cellValue, options) {
var item = options.rowData;
return item.so_enduser_id == undefined ?
'' :
'<a href="index.php?module=Accounts&view=Detail&record=' +
item.so_enduser_id + '">' + item.so_enduser_name + '</a>';
};
See http://jsfiddle.net/tztj9yn7/4/

JQGrid rendering performance

We have performance issues with JQgrid rendering. Please advise.
JQGrid v4.3.2, jquery-1.7.2.min.js, jquery-ui-1.8.1.sortable.min.js, jquery-ui-1.8.20.custom.min.js
Browser: IE6,7
Every user is shown data in 2 grids - actions and fyi's. Typical data range is ~300 rows in each grid. The list of columns could vary for user groups and hence the colModel structure is dynamic. After getting data we apply conditional styles to each row (to be bold or not etc) and change the number formatting.
Code sample for grid is as below:
jQuery('#ActionItems').jqGrid({
url: 'http://actionsurl',
mtype: 'GET',
datatype: 'json',
page: 1,
colNames: actionsColNames,
colModel: actionsColModel,
viewrecords: true,
loadonce: true,
scrollrows: false,
prmNames: { id: "PrimaryID" },
hoverrows: false,
jsonReader: { id: "PrimaryID" },
sortname: 'CreateDt',
sortorder: 'desc',
gridComplete: function () {
fnActionsGridComplete();
},
recordtext: "Displaying {1} of {2} Records",
emptyrecords: "No data to view",
emptyDataText: "No data found.",
loadtext: "Loading...",
autoWidth: true,
rowNum: 1000,
grouping: true,
groupingView: groupingViewOp
});
Formatting code in fnActionsGridComplete():
Set column widths in %
Iterate thru rows to apply conditional css styles
$("#Actions").find("tbody tr").each(function () {
if ($(this)[0].id != '') {
var data = $(this).find('.IsItemNew').html();
if(data == "Y") {
$(this).css("fontWeight", "bold");
}
}
});
Formatting for specific columns.
Currently we have performance issues for >200 rows of data in any grid. After analysis we found that formatting and rendering is taking most time.
Can you suggest any optimal way to improve performance here. (paging is no-no)
Regards,
Rajani
- We did testing on IE9 and its lot better. But users cant immediately upgrade.
The reason is the code fnActionsGridComplete. I recommend you to read the answer which explains why it's very important to use gridview: true and reduce the number of changes of DOM elements of the page.
What you try to do seems could be implemented by adding cellattr to the column "IsItemNew". The code could be about the following
cellattr: function (rowId, value) {
// additional parameter of cellattr: rawObject, cm, rdata are optional
if (value === "Y") {
return ' style="font-weight:bold;"';
}
}
Alternatively you can add class attribute instead of style and define font-weight: bold in the class.
I recommend you to read the answer, this one, this one etc. If you would need to set some properties on the whole row instead of the cell only you can use rowattr (see the answer).
If you would include gridview: true and use cellattr, rowattr or custom formatters you would see that the performance of the grid will be on absolutely another level.

Loading JSON data in jqGrid

I'm having troubles when showing my json data in jqGrid.
I've searched a lot in this forum and tried various forms to make it work. I apologize if this was already answered but I really need help with this one.
At the server page I was only using JavaScriptSerializer to send the data and the jsonreader function with the default parameters (this worked ok).
I now need to paginate and have changed my server page code to work with the sidx, sord, page, rows parameters.
The resulting string from the server looks like this:
{"total":"344","page":"1","records":"8577","root":[{"Id":"1","SerialNumber":"132","Name":"ServerName"},...]}
Here is my jQuery code:
$("#list").jqGrid({
datatype: "json",
mtype: 'GET',
url:'https://server/handlerpage.ashx',
colNames:['Id','SerialNumber','Name'],
colModel :[
{name:'Id', index:'Id', jsonmap:"Id", width:20},
{name:'Name', index:'Name', jsonmap:"Name", width:120},
{name:'SerialNumber', index:'SerialNumber', jsonmap:"SerialNumber", width:100}],
jsonreader: {repeatitems:false,id:'Id',root:'root'},
pager: '#pager',
rowNum:25,
rowList:[25,50,75,100],
sortname: 'Id',
viewrecords:true,
gridview: true,
height:"400",
width:"700",
caption: 'Select from existing server',
loadtext:'Loading, please wait'
}).navGrid("#pager", { edit: false, add: false, search: true, del: false });
In order to use json data as a response from a query the response has to be formatted correctly. It is difficult to determine what is the correct response and how to get it from the documents. More problems can occur as a result of your server settings generating a warning as part of the response which will cause the grid not to load.
From the documents this is the default json reader, meaning if you format your response correctly you don't need to add anything / a custom json reader.
jsonReader : {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: true,
cell: "cell",
id: "id",
userdata: "userdata",
subgrid: {
root:"rows",
repeatitems: true,
cell:"cell"
}
First make sure you have the right response format. {"page":1,"total":1,"records":"2","rows":[{"id":"1","cell":["1","mydata1"]},{"id":"2","cell":["2","mydata2"]}]}
No sample is given on the docs page but the above is correct if you only have two columns in your grid. You need to get your server query / parsing of your server query and values passed to the page that runs your sever side scripts to return this format. The example.php page from the documents gives you all the values you need.
This code will give you the proper header, to avoid error warnings and matches up with the response from above. Also note that in the docs they do not add the apostrophes around the indexes for the associative array index names. That will fail.
header('Content-type: application/json');$responce = new stdClass();$responce->page = $page;$responce->total = $total_pages;$responce->records = $count;$i=0;while($row = mysql_fetch_array($result,MYSQL_ASSOC)) {$responce->rows[$i]['id']=$row['ID'];$responce->rows[$i]['cell']=array($row['ID'],$row['entity_name']); $i++; } echo json_encode($responce);
To rehash what is missing in the docs (it is possible that I just missed them and even if, the documents for jQgrid are epic/a masters work):
1. No mention of the need for a header statement for json (it is clear with the XML examples)
2. No sample of what a working returned string should look like
3. Lack of proper formatting of the associative array indexes.
4. No mention of how to avoid a PHP warning being returned as part of the response
Try the following
jsonReader: {
root: 'rows',
page: 'page',
total: 'total',
records: 'records',
repeatitems: true,
cell: 'cell',
id: 'id',
userdata: 'userdata'
}
Please make sure that the server side script is returning proper json string with HEADERS
Further check the demo site and JSON example

Jqgrid: Load data after Grid load?

I am using jqgrid 4.0 .The grid is loaded on page load using 'local' datatype , loadonce:'true' and I don't want to use pagination. Since the data that is to be loaded is huge, it takes lot of time to get loaded. How can I
load the grid only first with headers, displaying a load text as 'loading....' and then load the data? Right now, both the grid and data loads together and page doesnt appear until this is complete.
Load the data faster in grid?
Below is my code snippet where 'data' is the json encoded array formed server side.
<script type="text/javascript">
jQuery("#list9").jqGrid({
data: data,
datatype: "local",
colNames:[...],
colModel:[...],
sortname: 'fld_name',
rowNum: '-1',
loadonce:true,
mtype: "GET",
gridview: true,
viewrecords: true,
sortorder: "asc",
pager: '#pager9',
rownumbers: true,
multiselect: false,
width: '100%',
pgbuttons:false,
pgtext:'',
loadtext: 'loading....',
ignoreCase: true
});
jQuery("#list9").jqGrid('filterToolbar', {stringResult: true,searchOnEnter : false});
$('.ui-widget-header').css("background", "#7B9FBC");
$('.ui-jqgrid-sortable').css("text-align", "left");
</script>
What I do is:
First, render the grid without any data.
var grid = $('#myGrid');
grid.jqGrid({
data: [],
datatype: "local",
colModel: [ ...
Then, add the data to the grid using addRowData.
var grid = $('#myGrid');
grid.jqGrid('addRowData', 'ContactID', newRowData, 'first');
It sounds like you have your data already in memory when you build the grid, and it's just taking a long time to render the grid. This might be because of all the DOM objects being created when rendering the grid. There isn't much you can do about that other than paging, or decrease the complexity of your cells if you are using heavy formatting.

why does jqGrid give "Error: No url is set" if cellSubmit is 'clientArray'?

using jqGridversion 3.7.2
I thought that if I set cellSubmit: 'clientArray' then the grid does NOT need a url to post data. I'm trynig to just capture the changed value locally and process it manually, not auto trigger a server event. Yet when I try to exit an edited cell I still get the "Error: No url is set" dialog.
grid options def:
$(".mytable").jqGrid({
datatype: 'local',
data: myData,
colModel: colModelDef,
sortname: 'date',
sortorder: 'desc',
width: 950,
height: 550,
shrinkToFit: false,
rownumbers: true,
multiselect: true,
cellEdit: true,
beforeSaveCell: function() {
//rowid, cellname, value, iRow, iCol
alert(arguments[2]);
},
cellSubmit: 'clientArray'
});
turns out it was a typo, should read "cellsubmit" not "cellSubmit" works like a charm. Thanks Tony!
Before all you should replace class selector $(".mytable") to the id selector like $("#mygrid"). If the <table> element not yet has the id you should add it. jqGrid works intern permanent with the id of the table element and construct ids of other DOM elements based on the id of the <table> element. So the usage of <table> without id can not good work.
If a simple change of the selector will not help you should include full code of an example which can be used to reproduce the problem.
add follow attr and the error will be gone
loadonce:true

Resources