jQgrid change paramaters sent to server - jqgrid

I am using cookies to load a users previous sorting and paging options. I would like to take those saved values, and set them as the parameters the server receives.
The paramaters I wish to change are as follows, (rows are replaced by max via prmNames)
/&max=20&page=1&sidx=&sord=asc
I have tried using:
$.extend($.jgrid.defaults, {
sidx:"fName",
sord:"desc",
page:2,
rows:10});
and variations of:
beforeRequest:function(){
$('#grid').jqGrid('setGridParam', {
sidx: "fName",
sord: "desc",
page: 2,
max: 10
});
}
It changes the value for page using $.extend($.jgrid.defaults... , but I cannot get the other parameters to change.

You need just use setGridParam to set parameters of jqGrid which have another names as sidx, sord, page and rows.
sidx -> sortname
sord -> sortorder
page -> page
rows -> rowNum
So the best would be to create jqGrid directly with the above parameters initialized from the cookie.
If you would have problem with creation the grid directly with the parameters which you need you can first create the grid with datatype: 'local' which will prevent the loading the grid. Then you change the parameters which you need and additionally set datatype to the value which you need ('json' or 'xml'). At the end you reload the grid. So the code should be like the following
$('#list').jqGrid('setGridParam', {
datatype: 'json',
sortname: "fName",
sortorder: "desc",
page: 2,
rowNum: 10
}).trigger('reloadGrid');
If you would have problem with creation the grid directly with the parameters which you need. additionally create the grid with datatype: 'local' it will prevent the loading the grid

Related

Jqgrid inline edit for selectList hits server for each row

i have set ,
editoptions: { aysnc: true, dataUrl: 'ControllerName/MethodName?__SessionKey=' + sessionkey + "&Id=" + Id, buildSelect: buildSelectFromJson, style: "width: calc(100% - 65px);",
dataEvents: [
{
type: 'change',
fn: function (e) {}
}
]
}
in which buildSelectFromJson returns select list in html.
Now dataurl hits server for each row but my select list is same for all rows. so how can i restrict to a single hit and then use that select list for all other rows?
I can suggest you two alternatives:
the server code (responsible for the URL ControllerName/MethodName) can place HTTP caching header. For example Cache-Control: private, max-age=(time in seconds). It will force getting the data during specified time interval from the local web browser cache.
You can make Ajax request to ControllerName/MethodName separately and set editoptions.value based on the response instead of usage editoptions.dataUrl (only if dataUrl is undefined the value will be used). See the answer for the code example of the possible implementation. By the way you can combine the call to ControllerName/MethodName with the main call for filling the grid. See the answer and this one.
By the way the property aysnc: true which you use in editoptions is unknown and it will be ignored.

JqGrid Performance - setRowData lags

setRowData takes almost 5 seconds when the grid has 300 rows, 30 cols, and 4 frozen cols.
$("#tbl").jqGrid({
gridview: true,
url: '../controller/GetData',
datatype: "json",
rowNum: pageSize,
viewrecords: true,
loadtext: '',
loadui: 'disable',
rowList: [1000, 2000, 3000],
width: $(window).width() - LeftMargin,
shrinkToFit: false,
pager: '#dvPager',
pagerpos: 'left',
colNames: GetColNames(selectedViewName, viewCols),
colModel: GetColModel(selectedViewName, viewCols),
cmTemplate: {
title: false
},
recordtext: "Displaying {0} - {1} of {2}",
rowattr: function (rowData) {
},
//onCellSelect: function (rowid, iCol, cellcontent, e) {
// e.stopPropagation();
// proto.editcell(rowid, iCol, cellcontent, e);
//},
loadComplete: function (data) {..},
onPaging: function (data) {..},
serializeGridData: function (postData) {..}
});
Can you please guide me with the performance tuning tips?
In GetColModel we are binding columns as follows -
'Discount': {
name: 'Discount', index: 'Discount', width: colModelWidthDict['Discount'], title: false, sortable: false, resizable: colResizable, hidden: !bReadCalculationSellInfo,
formatter: function (cellValue, option, rowObject) {
if (rowObject.level == 0 || (rowObject.Flag == 0 && (rowObject.Discountable && rowObject.Discountable.toLowerCase() == 'no')))
return '';
else {
if (!proto.IsReadOnly(rowObject) && ((rowObject.Flag == 0 && (rowObject.Discountable && rowObject.Discountable.toLowerCase() == 'yes')) || rowObject.Flag > 0))
return proto.GetControls("Discount", option.rowId, "Numeric", rowObject.Discount, 6, 90)
else
return '<span class="amt">' + cellValue + '</span>';
}
},
unformat: function (cellValue, option) {
return cellValue;
},
cellattr: function (rowId, val, rowObject, cm, rdata) {
if (parseInt(rowObject.PPPChngDisc) == 1)
return ' style="color:red"';
}
}
//code for colModel - 1 column above
In general you should prefer to modify only small number of rows. If you modify one row then the web browser have to recalculate position of all other rows (500 rows) of the grid. In the case modifying 300 rows means 300*500 operations for the web browser.
If you fill the whole grid and you use gridview: true option then jqGrid places at the beginning all the data for the grid body in array of strings. After preparing of all information in string format jqGrid place the whole body of the grid as one operation. It's just one assigning innerHTML property of tbody. Thus it's more effective to reload the whole grid as to make modification of many rows of the grid in the loop using setRowData.
So I would recommend you to reload the grid in your case.
Moreover you should consider to reduce the number of rows in the page of grid. If you use rowNum: 500 you just reduce the performance of your page tin many times without any advantage for the user. The user can see about 20 rows of the data only. Only if the user scrolls he/she is able to see another information. In the same way the user could click next page button. Holding 500 rows force web browser make a lot of unneeded work. Modifying of the first row from 500 the web browser have to recalculate position of all 500 rows. Even if the user move the mouse over a row the web browser change the class of the hovering row and it have to recalculate position of all other from 500 rows event the rows are not visible.
One more remark. The implementation of frozen columns in jqGrid 4.6 is slow. Starting with the end of 2014 and publishing 4.7.1 with changing Lisanse and making jqGrid commercial I develop free jqGrid as fork based on jqGrid 4.7 (see the readme for more details). I implemented a lot of changes and new features in the fork. The recent changes includes many improvement of frozen columns feature. If you loads free jqGrid or just try it directly from GitHub by including the corresponding URLs (see the wiki) you will see that the performance of frozen columns is dramatically improved. Additionally frozen columns supports now row and cell editing in all editing modes. I plan to publish free jqGrid 4.9 soon. So I recommend you to try it.
UPDATED: You posted the code, which you use in comments below. I see the main problem in the implementation of Process function which will be called on change in the <input> fields on the grid. I recommend you to try something like this one:
function Process(contrl) {
var $cntrl = $(contrl),
$td = $cntrl.closest("tr.jqgrow>td"),
$tr = $td.parent(),
rowId = $tr.attr("id"),
newValue = $cntrl.val(),
$grid = $("#list"),
p = $grid[0].p,
colModel = p.colModel,
columnName = colModel[$td[0].cellIndex].name, // name of column of edited cell
localRowData = $grid.jqGrid("getLocalRow", rowId),
iColTotal = p.iColByName.total;
// modify local data
localRowData[columnName] = newValue;
localRowData.total = parseInt(localRowData.quantity) * parseFloat(localRowData.unit);
// modify the cell in the cell (in DOM)
//$grid.jqGrid("setCell", rowId, "total", localRowData.total);
$($tr[0].cells[iColTotal]).text(localRowData.total);
return false;
}
One can event improve the code and not use setCell at all. It's important to understand that local grid hold the data in the form of JavaScript object. The access to the data is very quickly. You can modify the data without any side effects existing with DOM elements. In the above code I use only relative search inside of the DOM of the row using closest and parent. It works very quickly. I recommend to save $("#list") in the variable outside of the Process (move var $grid = $("#list") in the outer function) and just use $grid variable. It will make access to the DOM of page very quickly. The line localRowData = $grid.jqGrid("getLocalRow", rowId) get the reference to internal JavaScript data object which represent the internal data of the row. By modifying the data by localRowData[columnName] = newValue; or localRowData.total = ... we make the half of job. One need only to change the value in the DOM on the cell Total. I used iColByName which exist in the latest sources of free jqGrid on GitHub. It get just the column index in colModel by column name. One can find the same information alternatively if one use more old jqGrid. The line $($tr[0].cells[iColTotal]).text(localRowData.total); shows how to assign manually the data in the cell. It's the most quick way to do this, but one assign the data without the usage formatter. For more common case (for example in case of frozen "total" column) one can use the commented row above: $grid.jqGrid("setCell", rowId, "total", localRowData.total);.

Proper way to page jqGrid

I need to display a number of "dynamic" grids using jqGrid. By dynamic I mean that both definition and data of the grid are retrieved from a database. There are many grids on the page, so I am trying to minimize the number of server trips, and there is a lot of data, so server-side paging is a must.
My workflow is
On initialization of each grid, retrieve grid definition and first
page of data in one server call.
If a user sorts/pages, then retrieve a page of data from the server
Because I want to retrieve the grid definition and first page of data in one call, I cannot use datatype: 'json', url: '###' approach; instead I do:
grid.jqGrid({
mtype: 'post',
...
datatype: function (postdata) {
if (!init.data) {
var request = {
screenId: settings.screenId,
pageNumber: postdata.page,
pageSize: postdata.rows,
sortColumn: postdata.sidx,
sortDirection: postdata.sortd,
date: settings.date
};
site.callWs("/MyService", request, function (pageResponse) {
//WHAT TO CALL HERE TO SET A PAGE OF DATA?
});
} else {
//WHAT TO CALL HERE TO SET A PAGE OF DATA?
init.data = null;
}
}
});
My data object (pageResponse or init.data) looks like this
I am not sure what method to call on jqGrid once a page of data is returned. I considered addJSONData, but it seems so inefficient to convert JSON back to string, then use EVAL(). Also, considered addRowData or setting the data property, but I am confused how to instruct jqGrid that I am doing server-side paging -- if I set the data property to one page of records, what do I need to do to tell jqGrid that there is a total of 50 records and this is page 1 out of 10.
Thanks for your help.
It was a user error (mine :). I had some show/hide logic in loadComplete of jqGrid, but this event does not fire when addJSONData is called.
addJSONData works just fine when provided with a properly-structured JavaScript object.

How to supply a Row ID when using jqGrid 'editGridRow' to create a new row and not the auto generated Row ID jqg1

I'm new to jqGrid, so hopefully someone can point me in the right direction.
Basically, I am using jgGrid to display a list of dates and costs that I have read in from a file that I want the user to be able to amend or add new entries or delete existing entries. Upon the user clicking an onscreen button "Apply" to post back the form , I read out the jqGrid and post back to Server in the form of a JSON string.
My problem is that when I add new rows (via 'editGridRow'), jqGrid is using it's autogenerated jqg1, jg2, jg3, etc and the new rows are being populated at the top of grid instead of at their row id position i.e at the bottom of grid.
I am able to generate RowID's as necessary, however I do not seem to be able to supply them to 'editGridRow' when creating new entries, instead it appears I have to use the keyword "new".
As you are aware the reason I am using editGridRow instead of addRowData is that editGridRow creates a modal dialog for the user to enter the data.
Any help would be appreciated.
This is what I would like to use to supply a row ID:
$("#tableGrid").jqGrid('editGridRow', gridRowID, {reloadAfterSubmit:false});
This is what I have to use to get the code to work:
$("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false});
Here is the code snippet I use for creating the gqGrid in my JSP:
var gridRowID = ${costHistoryEntries}.length
$("document").ready(function() {
$("#tableGrid").jqGrid({
data: ${costHistoryEntries},
datatype: "local",
height: 200,
colNames:['Date', 'Cost'],
colModel:[
{name:'chdate', index:'chdate', width:110, sorttype:"date", editable:true, editrules:{date:true, required:true, custom:true, custom_func:checkDate}, datefmt:'d/m/Y'},
{name:'cost', index:'cost', width:160, align:"right", sorttype:"float", editable:true, editrules:{number:true, required:true}, formatter:'float'},
],
autowidth: true,
loadonce: true,
sortname: 'chdate',
sortorder: "desc",
rowList:[10, 20, 30],
pager: jQuery('#tablePager'),
viewrecords: true,
editurl: '/myurl',
caption: "Cost History Entries" }
);
$("#tableGrid").jqGrid('navGrid', "#tablePager", {edit:true, add:true, del:true, search:true, refresh:true});
$("#addEntry").click(function() {
gridRowID++;
$("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false});
});
});
I also created a button and linked it to "addEntry" as an alternative way to adding a new row using the jqGrid Navigator "add/edit/delete/find/reload" bar. As you can see previous to loading the grid with data I stored the number of entries in gridRowID. What I was hoping to be able to do in the "#addEntry" click function was use the updated gridRowID as a RowID parameter.
As a FYI:
In a previous version of the code I was using the following to load the data into the grid:
var griddata = ${costHistoryEntries};
for (var i=0; i <= griddata.length; i++) {
$("#tableGrid").jqGrid('addRowData', i+1, griddata[i], "last");
}
but found that I could do that same with
data: ${costHistoryEntries},
Both versions correctly create row ID's for the supplied sample data from the server:
[{"chdate":"20/05/2011","cost":"0.111"},{"chdate":"01/06/2011","cost":"0.222"},{"chdate":"07/07/2011","cost":"0.333"}]
My problem is adding new rows of data.
Further update, On the server side, as a test I intercepted the post to /myurl and updated the id from "_empty" to "7" but the new entry in jqGrid still has an autogenerated jqGrid Row ID "jqg1":
Key = chdate, Value = 26/09/2011
Key = oper, Value = add
Key = cost, Value = 14
Key = id, Value = _empty
Updated Key = chdate, Value = 26/09/2011
Updated Key = oper, Value = add
Updated Key = cost, Value = 14
Updated Key = id, Value = 7
I am not quite understand your requirement. You get the input for the jqGrid from the server, but use datatype: "local" instead of the datatype: "json" for example which instruct jqGrid to get ajax request to the server to get the data whenever as needed. Moreover you want to save the date on the server, but use editurl: '/dummyurl' instead of the real server url. The editurl would get the input data from the $("#tableGrid").jqGrid('editGridRow', "new", {reloadAfterSubmit:false}); and should post back the id of the new generated row. Is it not what you want?
So my suggestion would be to use some server based datatype (the bast is datatype: "json") and in the same way use real editurl which save the data on the server (in the database mostly) and place in the server response the id on the new generated data item.
UPDATED: If you use reloadAfterSubmit: false option of the editGridRow you have to use afterSubmit event handler together with reloadAfterSubmit which decode the server response and return the result in the format [true,'',new_id] For example if your server just return new rowid as the data you can use
$("#tableGrid").jqGrid('editGridRow', "new",
{
reloadAfterSubmit: false,
afterSubmit: function (response) {
return [true, '', response.responseText];
}
}
);

jqGrid does not selects cell value as a selected dorp down value In edit mode

I am using jqGrid v 4.0 in my application to display tabuler data with Inline edit feature. One of the column in the Grid is a type of "Select". I have populated this select with following server side code:
//get all Departments
HRDept = $.ajax({
url: '../../PerformanceReview/GetHRDepartments/',
async: false,
success: function(data, result) {
if (!result)
alert('Failure to retrieve the HR Departments.');
}
}).responseText;
I have populated the Grid column with following sysntax:
name: 'HRDepartment', index: 'Department', align: 'left', editable: true, edittype: 'select', editoptions: {value: HRDept}
But on click of edit button (inline), it shows dropdown on on top of cell but the value is not equal to current cell value. it is always first value of drop down. I had compared the text which i am populating while loading Grid with the text of Dropdown and they are matching.
Could some one help me to set dropdown value similar as cell value.
Your edit options look wrong, it should be "value:text;" and the value should match your data results.
{ ... editoptions: {value: "HRDept:HR Department;" }}
You can checkout the demo of Row Edition -> Input Types at the jqGrid Demo site., which includes a dropdown list edit cell.
If you get the select values from the server you should use dataUrl option of the editoptions instead of value. Then the jqGrid will make the Ajax request at the beginning of the editing and fill the select element with the server response. It is important to understand that the server response should be in another form:
<select>
<option value='101 - Equity Partners'>101 - Equity Partners</option>
…
</select>
If you have already the code on the server which provide the information in another format and you can't change the server code you can define additional buildSelect function which get as the parameter the server response and should return the data in the above format ('...'). See UPDATED part of the answer for the code example.

Resources