Grid not working after reloading on alternate calls - jqgrid

$("#tableVisualization").jqGrid('GridUnload');
$("#tableVisualization").jqGrid({
datatype: "local",
mtype: 'GET',
colNames: this.GetGridColumnNames(),
colModel: this.GetGridColumnModel(),
height: "100%",
autowidth: true,
shrinkToFit: true,
sortname: 'monthID',
sortorder: "desc",
rowList: [6, 12],
rowNum: 12,
pager: $('#pager3'),
viewrecords: true,
recordpos: "left",
caption: "Table"
});
//local data array used for example
var data = this.GetGridData();
//FUNCTION CALL
//populate grid with data
$("#tableVisualization").jqGrid("addRowData", "month", data);
$("#tableVisualization").trigger("reloadGrid");
$("#tableVisualization").setGridWidth(1040, true);
Above code works fine.
However if I assign $("#tableVisualization") to a variable and use the variable in the above code it does not work.
//var grid = $("#tableVisualization");
It works every alternate call.
For example if the whole code was inside a javascript method called LoadGrid(), then the first call to the method works, second call does not, third works, fourth does not and so on.
I have seen during debugging, when it reached "grid.jqGrid('GridUnload')" on the even calls, the grid is completely removed(im not sure if the html table is removed or not) and it is not created during "$("#tableVisualization").jqGrid({.....});".
Can anyone please explain me the reason for this behaviour.
I can make the scenario work because now I am not using a local variable but I would like to know why it does not work?

We can see exactly what is going on within the grid's GridUnload method in grid.custom.js:
GridUnload : function(){
return this.each(function(){
if ( !this.grid ) {return;}
var defgrid = {id: $(this).attr('id'),cl: $(this).attr('class')};
if (this.p.pager) {
$(this.p.pager).empty().removeClass("ui-state-default ui-jqgrid-pager corner-bottom");
}
var newtable = document.createElement('table');
$(newtable).attr({id:defgrid.id});
newtable.className = defgrid.cl;
var gid = $.jgrid.jqID(this.id);
$(newtable).removeClass("ui-jqgrid-btable");
if( $(this.p.pager).parents("#gbox_"+gid).length === 1 ) {
$(newtable).insertBefore("#gbox_"+gid).show();
$(this.p.pager).insertBefore("#gbox_"+gid);
} else {
$(newtable).insertBefore("#gbox_"+gid).show();
}
$("#gbox_"+gid).remove();
});
},
The key points to understand are:
A new table element is inserted with the same DOM id as the old table. We can see it created in the call to document.createElement('table') and inserted in one of the calls to insertBefore.
The existing jqGrid DOM is removed in the call to $("#gbox_"+gid).remove(). Since the old table element is contained within the gbox, it is removed as well.
After the call to GridUnload, the DOM element that it refers to no longer exists on the page, so any code that references the element is ineffective.
Does that help?

Related

jqgrid formatting based on certain value. spring jqgrid

I am new to the JQGRID, I need to format jqgrid based on certain values, lets say if the "NAME" column contains value of "HEMA" and "RAJU" then their respective row should contain the value of n/a (meaning their gender, mobile, location , country should be n/a). I am stuck as I could not figure out how to approach this problem in jqgrid. Guidance will be highly appreciated. I have attached image for clear explanation.
I did some searching but could not find anything closest I could find was formatter but did not work.
var url = "test/gridresult";
$(function(){
("#result").jqGrid({
url:url,
datatype: "jsonstring",
multiselect:false,
colNames:['Id','NAME', 'GENDER', 'MOBILE','LOCATION','COUNTRY'],
colModel:[
{name:'id',index:'id', resizable:true},
{name:'name',index:'name', resizable:true},
{name:'mobile',index:'mobile', resizable:true},
{name:'country',index:'country', resizable:true},
],
rowNum:100,
pager: '#prowed1',
sortname: 'id',
loadonce: true,
sortorder: "desc",
jsonReader;{
repeatitem:false,
root:"rows",
page:"page",
records:"records",
cell:""
}
});
});
this seems working, I am getting name from loop but how do I set n/a in a row for that particular name
var rows = $("#result").jqGrid('getDataIDs');
for (var i = 0; i < rows.length; i++)
{
var status = $("#resultTable2").getCell(rows[i],"NAME");
alert("initial value "+status);
if(status == "HEMA")
{
//need to set value of n/a for row that belongs to HEMA
}
}
<!-- begin snippet: js hide: false console: true babel: false -->
demo pic for my question
Guys I was able to fix it using formatter. Spent good amount of time and finally got it fixed.
function valFormat( cellvalue, options, rowObject ){
var val;
if(rowObject.name=='HEMA' ){
val='N/A';
}else{
val=cellvalue;
}
return val;
}
and in the jqgrid:
{name:'name',index:'name', resizable:true, formatter:valFormat},

JQuery Responsive Datatable doesn't work if table is ever empty

I have a responsive datatable defined as follows:
function loadCancellations(date) {
$('#cancellations').dataTable({
bDestroy: true,
bProcessing: false,
bServerSide: false,
bAutoWidth: false,
ajax: {
url: 'Modules/Bookings/',
data: {date: date, type: 'cancelled'}
},
sPaginationType: "full_numbers",
iDisplayLength: 50,
bLengthChange: false,
bPaginate: false,
bFilter: false,
bSort: true,
sDom: 't',
rowId: 6,
columns: [/*responsive column information*/],
order: [[0, 'asc'],[1, 'asc']],
asStripeClasses: ['', 'altrow'],
language: {
emptyTable: 'No cancelled bookings for this day'
},
fnCreatedRow: function( nRow, aData, iDataIndex ) {
// last column replaced with buttons
}
});
}
This function is called when the value of a datepicker changes, so it always refreshes the table with the cancelled bookings on the selected day. There are six columns (plus the buttons), two are always hidden until the row is expanded using the responsive interface in the first column, and I've tested it multiple times and it works fine.
except
If the table is ever empty, the responsive interface never works again. Instead it kicks a console error that says TypeError: a[0].aoData[this[0]] is undefined. So if it loads full, then I load a day that doesn't have any, and then I load another day that has some, the responsive plugin breaks. It doesn't matter whether I then destroy and re-initialize the datatable, it simply refuses to work. I can even go back to a date that had working rows - they don't work any more.
Does anyone have any ideas for a solution to this?
The plugin I was using was out of date. This was solved in a later version. I should have checked this before posting, and I feel shame for it.

jqgrid frozenColumns + (cell Edit & sortable/reordering of non frozen columns)

Please guide me on a work around for having a set of columns frozen and the rest having cell edit feature along with column reordering/ show- hide options using jqgrid.
Thank You.
Please try this, simple solution,
Hide or remove cellEdit: true
Then add the below lines in above and below the setFrozenColumns
Previous code:
$("#jqGrid2").jqGrid('setFrozenColumns');
New Code:
$("#jqGrid2").jqGrid("setGridParam", {cellEdit: false, sortable: false});
$("#jqGrid2").jqGrid('setFrozenColumns');
$("#jqGrid2").jqGrid("setGridParam", {cellEdit: true, sortable: true});
The problem is that the current implementation of setFrozenColumns have some restrictions. Editing (in any editing mode) and sortable: true is not allowed for frozen columns, but setFrozenColumns. Moreover sortable: true should don't allow to resort headers of frozen columns. On the other side setFrozenColumns contains simple test of some parameters (see here) and the method do nothing if some such parameters (like cellEdit or sortable) are set.
I suggested in the post (with the demo) the way how to implement a workaround. The way is modification of approach from the answer and this one.
I find your question interesting and so I created the demo which demonstrates how one do can implement your requirements. It displays the following results (animated gif):
It uses mostly the following code
// create the grid
$grid.jqGrid({
...
});
$grid.bind("jqGridLoadComplete jqGridInlineEditRow jqGridAfterEditCell jqGridAfterRestoreCell jqGridInlineAfterRestoreRow jqGridAfterSaveCell jqGridInlineAfterSaveRow", function () {
fixPositionsOfFrozenDivs.call(this);
});
$grid.jqGrid("setGridParam", {cellEdit: false, sortable: false});
$grid.jqGrid("setFrozenColumns");
$grid.jqGrid("setGridParam", {cellEdit: true, sortable: true});
fixPositionsOfFrozenDivs.call($grid[0]);
try {
var p = $grid.jqGrid("getGridParam"), tid = $.jgrid.jqID(p.id), colModel = p.colModel, i, n = colModel.length, cm,
skipIds = [];
for (i = 0; i < n; i++) {
cm = colModel[i];
if ($.inArray(cm.name, ["cb", "rn", "subgrid"]) >=0 || cm.frozen) {
skipIds.push("#jqgh_" + tid + "_" + $.jgrid.jqID(cm.name));
}
}
$grid.jqGrid("setGridParam", {sortable: {options: {
items: skipIds.length > 0 ? ">th:not(:has(" + skipIds.join(",") + "),:hidden)" : ">th:not(:hidden)"
}}});
$grid.jqGrid("sortableColumns", $($grid[0].grid.hDiv).find(".ui-jqgrid-labels"));
} catch (e) {}

Why jqGrid is very slow when number of rows displayed increases?

When I display a small amount per page, it's quick and very good. When I increase it to 100 or more it starts getting slow. At 1000 it's unbearable! This is the code used for drawing the grid:
$("#stSearchTermsGrid").jqGrid({
mtype: "POST",
postData:{},
datatype: function(postdata) {
$.ajax({
url: 'ajax/ajax_termsSearchGridSimple.php',
data: postdata,
async: false,
dataType: "xml",
error: function(){
alert('Error loading XML document');
},
success: function(data,stat,xmldata){
//check error
var $error=$(data).find('error').text();
if($error!="0")
{
messageBox("Error",$error);
return;
}
//content
var $content=$(data).find('content').text();
if($content!="0")
{
var thegrid = $("#stSearchTermsGrid")[0];
thegrid.addXmlData(xmldata.responseXML);
}
}
});
},
colNames:["tId","term", "revTerm", "uType","freq","description","fId","facet","modifiedTime"],
colModel:[
//tId
{name:'tId',index:'tId',align:"center",searchoptions:{sopt:['eq','ne','lt','le','gt','ge','in','ni']}},
//term (editable)
{name:'term',index:'term',searchoptions:{sopt:['eq','ne','in','ni','bw','bn','ew','en','cn','nc']},editable:true,edittype:'text',editoptions:{size:20},editrules:{required:true},formoptions:{elmsuffix:'(*)'}},
//revTerm (editable)
{name:'revTerm',index:'revTerm',searchoptions:{sopt:['eq','ne','in','ni','bw','bn','ew','en','cn','nc']},editable:true,edittype:'text',editoptions:{size:20},editrules:{required:true},formoptions:{elmsuffix:'(*)'}},
//uType (editable)
{name:'uType',index:'uType',align:"center",searchoptions:{sopt:['eq','ne','in','ni']},editable:true,edittype:'select',editoptions:{value:{'':'any','NPU':'proper noun','NU':'noun','VU':'verb'}}},
//freq
{name:'freq',index:'freq',align:"center",searchoptions:{sopt:['eq','ne','lt','le','gt','ge','in','ni']}},
//description (editable)
{name:'description',index:'description',searchoptions:{sopt:['bw','bn','ew','en','cn','nc']},editable:true,edittype:'textarea',editoptions:{rows:"3"}},
//fId
{name:'fId',index:'fId',align:"center",searchoptions:{sopt:['eq','ne','lt','le','gt','ge','in','ni']}},
//facet
{name:'facet',index:'facet',searchoptions:{sopt:['eq','ne','in','ni','bw','bn','ew','en','cn','nc']}},
//modifiedTime
{name:'modifiedTime',index:'modifiedTime',align:"center",searchoptions:{sopt:['eq','ne','lt','le','gt','ge','bw','bn','ew','en','cn','nc']}}
],
gridComplete: function(){
var $ids=$("#stSearchTermsGrid").jqGrid('getDataIDs');
for($i=0;$i<$ids.length;$i++){
var $reference="G";
//update columns
$("#stSearchTermsGrid").jqGrid('setRowData',$ids[$i],{"reference":$reference});
//coloring the recently classified row
var $colorRecentlyModified = '#DFFC91';
var modifiedTime = $("#stSearchTermsGrid").jqGrid('getCell',$ids[$i],'modifiedTime');
var timeDiff = Math.abs(new Date() - new Date(modifiedTime.replace(/-/g,'/')));
// 86400000 is the number of milliseconds in one day. Multiplying by days to mark the ones which are modified a few days ago
timeLimit = 86400000 * 1.5;
if(timeDiff < timeLimit)
{
for(colN=2; colN<9; colN++)
$("#stSearchTermsGrid").jqGrid('setCell', $ids[$i], colN, '', {'backgroundColor':$colorRecentlyModified});
}
//coloring the unclassified row
var $colorUnclassified = '#FFCECE';
var $fId = $("#stSearchTermsGrid").jqGrid('getCell',$ids[$i],'fId');
if($fId == "0")
{
for(colN=2; colN<9; colN++)
$("#stSearchTermsGrid").jqGrid('setCell', $ids[$i], colN, '', {'backgroundColor':$colorUnclassified});
}
}
},
sortable: true,
//autowidth:true,
width: 900, //width for grid
height: 250, //height for grid
sortname: 'term', //default sort column
caption: "Terms", //caption for grid (empty will hide)
hidegrid: false,
gridview: true, //load the grid more fast
multiselect: true, //support mulitselect
//multiboxonly: true,
pager: '#stSearchTermsGridPager',
rowNum:10,
rowList:[10,25,50,100,500,1000],
viewrecords: true, //show view record information
viewsortcols: [true,'vertical',true], //show sortable column with icons
editurl: 'ajax/ajax_termsEdit.php'
});
$("#stSearchTermsGrid").jqGrid('navGrid','#stSearchTermsGridPager',
{edit:true,add:false,del:true,search:true,view:true,refresh:true},
// edit options
{
onclickSubmit : function(params, posdata) {
var $tId=$("#stSearchTermsGrid").jqGrid('getGridParam','selrow');
if($tId && $tId.length>0)
{
var $rowAry=$("#stSearchTermsGrid").jqGrid('getRowData',$tId);
var $fId=$rowAry["fId"];
return {"fId":$fId}
}
},
afterSubmit : gridAfterSubmit,
reloadAfterSubmit: true,
closeOnEscape:true,
bottominfo:"Fields marked with (*) are required."
},
// add options
{},
//del options
{
msg: "Selected records(s) will be permanently deleted and cannot be recovered.<br/> Are you sure?",
afterSubmit : gridAfterSubmit,
reloadAfterSubmit: true,
closeOnEscape:true
},
// search options
{multipleSearch:true,closeOnEscape:true},
//view options
{
closeOnEscape:true
}
);
$("#stSearchTermsGrid").jqGrid('gridResize',{minWidth:900,maxWidth:2000,minHeight:250, maxHeight:1000});
I see many places where the grid can be improved.
1) You should use paging. If you show the user 1000 rows of data, the data will be not displayed on the monitor at once. The user have to scroll the windows of web browser to see the most parts of data. Which sense has to spend time to paint the parts of window which will not be seen? The scrolling of data with respect of jqGrid is much more effective as scrolling of browser window. Moreover no person are able to analyse the 1000 rows of data. He have to change sorting and set different filters to understand which from the data are interesting for him. It is one more argument for the data paging and implemented some searching. It you already use advanced searching you can consider to use additionally toolbar searching with the parameter stringResult:true which is compatible with the advanced searching.
2) you should rewrite the code of gridComplete totally. I suppose, that for relatively large number of rows the function is the bottleneck of your code. To verify this just temporary comment the function and compare the time of the grid painting. You should understand that every time you get data by id or set data by id jQuery will have to search the DOM element by id. Especially modification of data on the page can be very slow. By the way it seems to me that you set the same 'background-color' (what is 'backgroundColor' ???) CSS style for almost the whole cells of the rows. Why not set the 'background-color' for the row (<tr> element) instead?
3) I strictly recommend you not use datatype as function. Your server part should return some error HTTP code. In the case the loadError event will work and you can decode and display the custom error message. All other in your data seems be standard and you need not use datatype as function. If you will use datatype:"xml" you can for example try to use loadonce:true and implement client-side data paging and sorting if you will have problem with implementation of this features on the server.
I don't want to write too long text so I stop on the 3 most important points. By the way if you will switch from XML to JSON as the datatype used for the communication with the server, it will also improve a little the performance.
UPDATED: To see the performance of jqGrid with 1000 rows of data without paging and with data paging look at the links. Is by the way the performance of my example with 1000 rows without paging also so slow as in your case?

jqGrid - edit data

I am quite new to jquery and jqgrid. I use ASP.NET WebForms. I am able to get some data prom server and show it in grid. I use PageMethods to get data from server. Usually my code is
function CreateGrid(){
$("#sestGrid").jqGrid({
datatype: GetData,
//toolbar: [true, "top"],
colNames: ['Name', 'Age'],
colModel: [
{ name: 'Name', index: 'Name', width: 170, align: 'left',
sortable: false, key: true },
{ name: 'Age', index: 'Age', width: 40, align: 'center',
sortable: false, editable: true },
],
ondblClickRow: function () {
var row_id = $("#sestGrid").getGridParam('selrow');
$('#sestGrid').editRow(row_id, true);
}
});
}
function GetData() {
PageMethods.GetSestevalniStevecData(GotData);
}
function GotData (data) {
$("#sestGrid").clearGridData(false);
for (var j = 0; j <= data.length; j++)
$("#sestGrid").jqGrid('addRowData', j + 1, data[j]);
}
So, now I would like to edit some data and post it to server. How can I do that using PageMethods? Should I use any other approach?
And one more thing. I checked the demos http://trirand.com/blog/jqgrid/jqgrid.html and in all edit examples you are able to edit only one row and then you have to save changes… Is it possible to edit more than one row and save all changes in one step?
Thanks all.
jqGrid is designed to be used together with ajax services. So if the user change the data of some row then the changes will be send to the server: to the URL which you configure through jqGrid parameter editurl. So the easiest way to implement row editing will be to include an ASMX web-service or a WCF service in you web site. It is not important whether you use ASP.NET WebForms, ASP.NET MVC or just pure HTML for your pages. So just choose the technology which you prefer and add the corresponding page to your site.
The ASMX or WCF should has a method with the signature like
public string MyDataEdit (string Age, string oper, string id)
(see this old answer for more information). The method should return the id of the new added item (the Name in your case) in case of Add operation.
One more small remark. You can change the definition of the ondblClickRow function from function() to function(row_id) and remove the line used getGridParam('selrow').
I used your example and changed it a bit:
ondblClickRow: function (rowid) {
if (rowid && rowid != lastsel) {
changedRows.push(rowid); //keep row id
jQuery('#jqgrid').editRow(rowid, true);
}
}
Under the save button click event:
$.each(changedRows, function () {
var row = $("#jqgrid").getRowData(this);
var Id = row['ID'];
var price = $(row['Price']).val(); //this is an input type
});
HTH someone :)

Resources