JqGrid doesn't close form edit after reloadGrid triggered - jqgrid

:-)
I think I encountered probably a bug on jqGrid 5.8.3 js I am using, but I am not sure…I wrote this code to refresh grid after submit the formedit:
ondblClickRow: function(rowid) {
jQuery(this).jqGrid(‘editGridRow’,
rowid,
{
editCaption: “Update”,
recreateForm:true,
dataheight: 180,
height: 270,
width: 350,
top: 40,
left: 170,
onclickSubmit : function (options, postdata) {
if( confirm(‘Update this record (Y/N)?’) ) {
//var rowid = postdata[this.id];
console.log( JSON.stringify(postdata) );
return {
// myParam: $(this).jqGrid(“getCell”, rowid, “URL”)
// test : “bla bla”
returndata : JSON.stringify( postdata )
//returndata : postdata
};
}
},
errorTextFormat: function (data) {
return ‘Error: ‘ + data.responseText
},
closeOnEscape: true,
closeAfterEdit: true,
afterSubmit : function() { $(“#grd-points_registry”).jqGrid(‘setGridParam’,{datatype:’json’}).trigger(‘reloadGrid’); }
//reloadAfterSubmit: false,
//aftersavefunc : function() { setTimeout( function() { $(“#grd-points_registry”).trigger(“reloadGrid”); }, 10); }
}
);
}
since I found searching on the web about .trigger(‘reloadGrid’) to force reloading after edit/add but the editform won’t close after triggered the reloadGrid thing and in debug on Chrome I see this:
jquery.jqGrid.min.js?ver=5.8.3:652 Uncaught TypeError: Cannot read properties of undefined (reading ‘0’)
at Object.complete (jquery.jqGrid.min.js?ver=5.8.3:652:172)
at fire (jquery.js?ver=3.6.0:3500:31)
at Object.fireWith (jquery.js?ver=3.6.0:3630:7)
at done (jquery.js?ver=3.6.0:9811:21)
at XMLHttpRequest.<anonymous> (jquery.js?ver=3.6.0:10057:9)
but all fields are numbers in this case …. same thing occurs also on edit and add inside navgrid pager…. any idea?
Thanks! Cheers!
Luigino

You do not need to do reloadGrid in afterSubmit, since the grid do reloading automatically after the data is posted to the server. In your case you do two reloading one after other which causes unexpected behavior
Actually reloading in form editing is option and you can disable and enable it. By default the reloading is on.
In your case I suggest you to set Json datatype in onclickSubmit event (if no errors) and not reload the grid, since the parameter is set and when you submit the data it is reloaded (because of json datatype already).
I highly recommend you first to read the docs.

Related

jqGrid applying sort from known values not working

I have a jqGrid and want to apply user's sort values after it loads. These values are saved and retrieved in jquery cookies. I am storing data in cookies because user will go to another url and come back which initiates page load and they want to be in same spot they left.
I have a loadPreferences function being called within loadComplete.
See code snippet below(I left several jqrid properties out to keep posting short).
// Set up the jquery grid
$("#jqGridTable").jqGrid(
{
// Ajax related configurations
url: jqDataUrl,
datatype: "json",
mtype: "GET",
autowidth: true,
// Configure the columns
colModel: columnModels,
// Grid total width and height
height: "100%",
// customize jqgrid post init
gridComplete: function()
{
CRef.updateJqGridPagerIcons("jqGridTable");
},
// Default sorting
sortname: "LastName",
sortorder: "asc",
sorttype: "text",
sortable: true,
jsonReader:
{
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
userdata: "userdata"
},
loadComplete: function (data)
{
if (boolPreferencesLoaded == false)//page level variable
{
boolPreferencesLoaded = loadPreferences(this);
$("#jqGridTable").trigger("reloadGrid");
}
isGridSorting(this, false);
}
...the rest of grid properties...
and in the function call(which is located in another js file), I have...
function loadPreferences(gridId)
{
if (typeof $.cookie("sortCol") !== "undefined")
{
$(gridId).jqGrid("sortGrid", $.cookie("sortCol"), true, $.cookie("sortOrd"));
}
return true;
}
function isGridSorting(gridId, sorting)
{
$.cookie("sortCol", $(gridId).jqGrid('getGridParam', 'sortname'));
$.cookie("sortOrd", $(gridId).jqGrid('getGridParam', 'sortorder'));
$(gridId).jqGrid('setGridParam', { postData: { isSorting: sorting } });
}
My problem is when I go to apply them on page load(with jqGrid specified above), it does not exactly work. The icon moves to correct column and the arrow is pointing in correct direction, but the data in column does not sort.
I know there are a lot of posts dealing with similar issues, but not able to get solutions to work. What I am trying to do seems to easy, but it's driving me nuts. If you respond, please make comment easy to understand. Thank you.

JQGrid loadui block not working

I would like to disable actions on JQGrid like clicking on checkbox, scrolling down the page when ajax operation is going on. I have tried to use loadui: 'block' in JQGrid but is not working. Any other set of code that needs to be added ?
Your question is not clear to me. But, if you want to block screen when you call an ajax function, you can do it on beforeSend and unblock it on complete :
$.ajax({
//type, url, etc.
beforeSend: function(){
$.blockUI.defaults.applyPlatformOpacityRules = false;
$.blockUI({
message : "Loading...",
centerY: 0,
baseZ: 2000,
css: { top: '0px', left: '', right: '512px' }
});
},
complete: function(xmldata, stat){
$.unblockUI();
}
});
But, if you're trying to make it on add/edit/delete event of jqGrid, you should block on onclickSubmit: function(params, postdata) { //block screen } and unblock it on afterSubmit: function(response, postData) { //unblock screen }. You can find more info about jqGrid events at this link and this one
Thanks for the reply. Couldn't make it work though.
Solved with below piece of code.
loadBeforeSend: function(){
var $gbox = $("#list").closest('.ui-jqgrid');
$gbox.block({
message: "<h1>Loading...</h1>",
css: { border: "3px solid #a00" }
});
},
loadComplete: function(data) {
var $gbox = $("#list").closest('.ui-jqgrid');
$gbox.unblock();
},

Apply Custom Formatter after Sort Function with jqGrid

I am using a custom control on an Xpage to build a table with jqGrid. The jqGrid receives the data via JSON and fills the table correctly.
My question is with the sort function of jqGrid. I apply a custom formatter to the cell value of my "docname" column when the table first builds. The issue that I am having is after sorting any of the columns this formatter becomes unusable. The format is still applied but this particular formatter builds a url that launches another Xpage and relies on the parameter "docid".
Here is my custom formatter:
function openDocument(cellvalue, options, rowObject) {
return "<a target='#{javascript:compositeData.target}' title='Open Document'
href='https://test.url.com?DocID=" +rowObject["docid"]+
"&action=#{javascript:compositeData.action}' class='doclink'>"
+ cellvalue + "</a>"; }
Is there any way to get the rowObject "docid" back into the openDocument formatter after sorting the grid?
I researched some and found the onSortCol event and have it initialized like this:
onSortCol: function(index,iCol,sortorder) {alert("Test")}
My alert that I have in the onSortCol initilization is working, I just need to find out how to set my "docid" parameter after the sort is run since it is currently set to undefined after the sort.
I have tried putting in:
{rowObject["docid"]}
But this just breaks the sorting all together.
I have also read these posts:
onSortCol Event
JQGrid Sorting - how to trigger onSortCol event
jqGrid - Is it possible to set onSortCol after init?
Thanks for your help.
Edit:
jqGrid Definition:
$().ready(function(){
jQuery("#listxGrid").jqGrid({
url:'#{javascript:compositeData.url}',
datatype: "json",
colNames:#{javascript:compositeData.colNames},
colModel:#{javascript:compositeData.colModel},
shrinkToFit: false,
jsonReader: {
repeatitems: false,
id: '#{javascript:compositeData.colID}',
root: function (obj) {
if ($.isArray(obj)) return obj;
if ($.isArray(obj.items)) return obj.items;
return [];
},
page: function () { return 1; },
total: function () { return 1; },
records: function (obj) {
if ($.isArray(obj)) return obj.length;
if ($.isArray(obj.items)) return obj.items.length;
return 0;
}
},
gridview: true,
loadonce: true,
ignoreCase: #{javascript:compositeData.ignoreCase},
rowNum: #{javascript:compositeData.rowNum},
rowList: #{javascript:compositeData.rowList},
rownumbers: #{javascript:compositeData.showRowNumbers},
height: #{javascript:compositeData.height},
caption: '#{javascript:compositeData.caption}',
pager: '#pagerxGrid',
viewrecords: true,
emptyrecords: '#{javascript:compositeData.emptyRecords}',
sortable: true,
onSortCol: function(index,iCol,sortorder) {alert(index)},
grouping: #{javascript:compositeData.grouping},
groupingView : {
groupField : #{javascript:compositeData.groupField},
groupDataSorted : true,
groupColumnShow : #{javascript:compositeData.showGroupCol}
}
});
Have a look at this answer which suggests the use of isArray to determine whether to use rowObject["docid"] or rowObject[integer]:
jqGrid - rowObject inconsistencies?
I ended up solving the problem this way. On the jqGrid it was receiving the "docid" param from the remote data on the first load just fine but as soon as the sort function called it would be set to "undefined."
As #PerHenrikLausten pointed out with his link, after the onload function completes this remote data type is then switched to local data. By loading in the docid into a hidden column, this is then available as a parameter for my formatter after the data type is switched.
By adding:
'Docid' as a colName & {name:'docid', index:'docid', hidden: true} to the colModel
It allows me to sort the jqGrid from any of my columns that I have sortable set to true with the docid parameter as what it should be not "undefined."
Thanks everyone for your input.

jqgrid retain filter on reload

This question has been as a lot so please forgive me asking again.
I have a grid loaded from a url.
I use loadonce: true
I use filtertoolbar:
$("#status").jqGrid('filterToolbar', { stringResult:true, searchOnEnter:false, autosearch: true, defaultSearch: "cn" });
I have a dropdown search list from which I can select what I'm looking for. Works great.
I have a navbutton I click to initiate a reload every 30 seconds. Works great.
$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-play', onClickButton: function ()
{
stint = setInterval (function() {
postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;
$("#status").jqGrid('setGridParam',{
url: './ar_status.cgi?systemtype=' + systype,
datatype: "json",
postData: postfilt,
search: true,
loadtext: "Refreshing grid...",
loadonce: true,
loadui: "block"
});
$("#status").jqGrid().trigger("reloadGrid");
}, 30000);
},
title: 'Start Auto Refresh (every 30 sec.)'
});
Using google chrome I can see the filters that were specified being posted to the server:
systemtype:production
_search:true
nd:1358887757603
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"}]}
I can change the filter between reloads and see the new, even multiple filters:
systemtype:production
_search:true
nd:1358887847592
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"},{"field":"dow","op":"cn","data":"MO"}]}
I am using multipleSearch: true on the initial load. I'm pretty sure that's retained on reload
On the grid, the filtertoolbar retains my filter criteria, both text and selects, but when the grid reloads, the filters are ignored and the entire dataset is diplayed in the grid.
I've tried many examples posted here on SO. I've tried adding [{current:true}] to the reloadGrid call - no difference. I can't seem to retain and apply the filters on a reload.
I would like the reload to always return the full dataset from the server (which happens fine), and allow the current filter settings to control what is shown after the reload. I do not want to use the postdata to build a new SQL select statement - server side filtering, because at any time the user may want to click the pause button, select a new filter and view something else from the entire dataset without another reload.
$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-pause', onClickButton: function ()
{
clearInterval(stint);
},
title: 'End Auto Refresh'
});
How can this be done without using cookies, as I saw in one post?
I could try using jqGridExport'ing the postfilt var, and then jqGridImport'ing it but was hoping for a more direct approach. I'm not even sure this would help since I already have everything I need right here in the grid via postData.
As a side note, in my setGridParam above, the loadtext I specify is never displayed. Instead, the default "Loading..." is displayed. All of the other parameters are working.
Many thanks in advance,
Mike
Solution. The complete loadComplete to retain filters, sort index and sort order after a [json] reload from the server:
loadComplete: function() {
var $this = $(this);
postfilt = $this.jqGrid('getGridParam','postData').filters;
postsord = $this.jqGrid('getGridParam','postData').sord;
postsort = $this.jqGrid('getGridParam','postData').sidx;
if ($this.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$this.jqGrid("setGridParam", {
datatype: "local",
postData: {filters: postfilt, sord: postsord, sidx: postsort},
search: true
});
$this.trigger("reloadGrid");
}, 50);
}
}
Thanks very much!!!!
I only added a bit to your solution to retain the page number as well:
loadComplete: function () {
var $this = $(this);
var postfilt = $this.jqGrid('getGridParam', 'postData').filters;
var postsord = $this.jqGrid('getGridParam', 'postData').sord;
var postsort = $this.jqGrid('getGridParam', 'postData').sidx;
var postpage = $this.jqGrid('getGridParam', 'postData').page;
if ($this.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$this.jqGrid("setGridParam", {
datatype: "local",
postData: { filters: postfilt, sord: postsord, sidx: postsort },
search: true
});
$this.trigger("reloadGrid", [{ page: postpage}]);
}, 25);
}
}
I am not sure, but I suppose that the origin of your first problem could be mixing postData.filters and postData and usage filter property instead of filters``. You use
postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;
to get filter property instead of filters. You get undefined value. So the setting postData to postfilt means nothing.
The next problem is that the server response contains non-filtered data. To force filtering the data locally you have to reload the grid once after the loading from the server have finished. You can do this inside of loadComplete. Exactly here you can set postData.filter if required, set search: true and trigger reloadGrid event. It's important only to do this once to have no recursion and you must don't set datatype back to "json" in the case. The datatype will be changed to "local" and the end of loading from the server in case of usage loadonce: true option. If you want apply filtering locally you have to reload grid once with options datatype: "local", search: true and postData having filters specifying the filter which need by applied. See the code from the answer or another one which do another things, but the code which you need will be very close.

jqgrid open subgrid only if there is some data

here is declarations of my subgrid:
subGrid : true,
subgridtype: 'json',
subGridUrl: 'manuf_subgr.php',
subGridModel: [{ name : ['Package','Sticker','Manufacturer'],
width : [85,50,100],
params: ['Catalogue']
}
],
gridComplete: function() {
var timeOut = 50;
var rowIds = $("#schedule").getDataIDs();
$.each(rowIds, function (index, rowId) {
if(rowId.row_cnt != 0){
setTimeout(function() {
$("#schedule").expandSubGridRow(rowId);
}, timeOut);
timeOut = timeOut + 200;
}
});
}
what I expect to happen is this line if(rowId.row_cnt != 0) preventing opening a subgrid if there is no data returned from json... yet all grids are open regardless...
can someone help to implement stop for opening empty subgrids?
full code:
jQuery("#schedule").jqGrid({
url:'sched.php',
datatype: "json",
mtype:'GET',
colNames:['Street_Date','Label','Catalogue', 'Artist', 'Title','UKDP','UPCEAN','format'],
colModel:[
{name:'Street_Date',index:'Street_Date desc, ID', sorttype:"date", formatter:'date', formatoptions: {newformat:'d/m/Y'}, width:75},
{name:'label',index:'label', width:100,align:"center"},
{name:'Catalogue',index:'Catalogue', width:85},
{name:'Artist',index:'Artist', width:120},
{name:'Title',index:'Title', width:250},
{name:'UKDP',index:'UKDP', width:35, align:"right", formatter:"number", sorttype:"float"},
{name:'UPCEAN',index:'UPCEAN', width:120, align:"center"},
{name:'format',index:'format', width:70, sortable:false}
],
height: "100%",
rowNum:20,
rowList:[10,20,30,50,100],
sortname: 'id',
viewrecords: true,
sortorder: "desc",
jsonReader : {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: true,
cell: "cell",
id: "id",
userdata: "userdata",
subgrid: {root:"rows", repeatitems: true, cell:"cell" }
},
pager: '#schedule_pager',
caption:"Release Schedule",
grouping:true,
groupingView : {
groupField : ['Street_Date']
},
subGrid : true,
subgridtype: 'json',
subGridUrl: 'manuf_subgr.php',
subGridModel: [{ name : ['Package','Sticker','Manufacturer'],
width : [85,50,100],
params: ['Catalogue']
}
],
gridComplete: function() {
var timeOut = 50;
var rowIds = $("#schedule").getDataIDs();
$.each(rowIds, function (index, rowId) {
if(rowId.row_cnt != 0){
setTimeout(function() {
$("#schedule").expandSubGridRow(rowId);
}, timeOut);
timeOut = timeOut + 200;
}
});
},
onSelectRow: function (rowId) {
$("#schedule").jqGrid ('toggleSubGridRow', rowId);
}
});
You write in the comment that you are newbie and it's the second day when you use it. jqGrid is relatively complex and your first example which you try to implement seems to me too complex for newbie. You try to load fill jqGrid with the data from the database and do grouping and subgrid in one grid.
What you try to implement in your demo can be solved by usage of expandOnLoad: true property of the subGridOptions option:
subGridOptions: {expandOnLoad: true}
You can see the feature on the official demo disguised under "Hierarchy" / "Expand all Rows on load". There are one important problem which I described in the answer. The problem is shortly the following: internal implementation of Ajax requests used in jqGrid prevent (skip) Ajax requests when another pending (not yet answered by the server) are working (see .grid.hDiv.loading in the places of the code here, here in the subgrid module and here, here and here). Neither expandOnLoad: true nor your current implementation can grantee that new Ajax request will be started during previous one still not responded. So you can have not all subgrids opened. You main question: "how to prevent opening of empty subgrids or how to hide it?", I find the second (and less important) question. Even if you see currently that your web site opens all subgrids it can be that access to the same site from more far place from the internet will follow opening of one or some subgrids only.
So I think that you should either change the design of your web page (change what you want to display in subgrids) or change the implementation so that you construct a queue with the list of subgrids which should be opened and you will open the next grid only after the previous one will be opened.
Alternatively you can includes the data for all subgrids in the response for the main grid. In the case you should use subGridRowExpanded callback to fill the grids as subgrid as grid. You you would use no caption and no pager option in the subgrids you will be get the same look as with the standard subgrids. Additionally you will have much more flexibility in the options. I personally prefer to subgrid as grid.

Resources