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) {}
$("#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?
I have the following JQ-Grid with a formatter function which returns some HTML as the column value:
jQuery("#list").jqGrid({
url:jsonUrl,
datatype: 'json',
mtype: 'GET',
colNames:['Id', 'Name', 'Phone', 'Action'],
colModel :[
{name:'id', index:'id', sortable:true},
{name:'name', index:'name', sortable:true},
{name:'phone', index:'phone', sortable:false},
{name:'details', index:'details', sortable: false,
formatter:function(cellvalue,options,rowObject){
return "<p class='trigger'><a href='#'><img src='/images/actions.jpg' /></a></p><div class='toggle_container'><div class='block'><table class='action'><tr><td><a href='#'><img src='/images/open.gif' /></a></td><td><a href='#'><img src='/images/edit.gif' /></a></td><td><a href='#'><img src='/images/delete.gif' /></a></td></tr></table></div></div>"
}
}
]
Later on, I try to get all the column / row data and export it to Excel. Is there a feature in JQ-Grid which allows you to export in Excel / PDF (fyi - I am using JSP/JAVA).
When I try to do something like this:
var mya=new Array();
mya=$("#list").getDataIDs(); // Get All IDs
var data=$("#list").getRowData(mya[0]); // Get First row to get the labels
I get a JavaScript error:
Message: 'l.p.colModel[...].name' is null or not an object
URI: http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/jquery.jqGrid.min.js
I think I may have an answer to your problem - or at least a workaround that will suffice. Take a look at the javascript below. This is the approach I use for ripping the data out of the grid:
var sCell;
var aDataIDs = $Grid.getDataIDs();
//Loop through table rows
for (var i = 0; i < aDataIDs.length; i++) {
try {
//Get row
var oRow = $Grid.getRowData(aDataIDs[i]);
}
catch (e) {
//If problem then fall back to this
for (var j = 0; j < _oJQGUserSettings.aColModel.length; j++) {
if (j > 0) sb.append('\t'); //Add tab
//Get cell data
sCell = $Grid.getCell(aDataIDs[i], _oJQGUserSettings.aColModel[j].name);
sb.append(sCell); //Add data
}
}
If you bear in mind that sb is a javascript stringbuilder class and _oJQGUserSettings.aColModel is just my encapsulation of the ColModel then this should probably give you what you need in terms of extracting the data from the grid as required. (I then copy it to the clipboard which allows me to paste the contents of the grid straight into Excel - handy!)
I suspect there is a bug in getRowData which is thrown when not all columns are displayed to the user. However I haven't isolated this for sure as yet.
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?
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 :)