This is an old revision of the document!


Cell Editing

cellEditing supports key navigation and editing individual cells, with the following behaviour:

  • When we click on a cell that is not editable, the cell is selected and we can use the up, down, left and right keys to navigate through the cells.
  • If we move to a cell that is editable, we can press [Enter] to edit the cell. The cell is saved when we press [Enter] again, when we press [Tab], or when we click on another cell. If we press [ESC], the cell is not saved. When editing a cell, the cursor keys move only within the cell.
  • When we click on cell that is editable, then we go directly into edit mode.
  • The cell is not editable if it has a class 'not-editable-cell', instead that in colModel is set to be editable

Installation

In order to use this module you should mark the Cell editing and Common when you download the grid. For more information refer to Download.
For Developers - this is the grid.celledit.js in the src directory.

The properties, events and methods used in cell editing are a sub-set of those of the parent grid, and described below

Properties

These properties are specific for cell editing and should be set in grid options

PropertyTypeDescriptionDefault
cellEditbooleanEnables (disables) cell editing. When this option is set to true, onSelectRow event can not be used, and hovering is disabled (when mouseover on the rows).false
cellsubmitstringDetermines where the contents of the cell are saved - can have two values: 'remote' or 'clientArray'.
If remote the content is immediately saved to the server using the cellurl property, via ajax. The rowid and the cell content are added to the url as name:value pairs. For example, if we save the cell named mycell,{id: rowid, mycell: cellvalue} is added to the url.
If 'clientArray', no ajax request is made and the content of the changed cell can be obtained via the method getChangedCells
remote
cellurlstringthe url where the cell is to be savednull
ajaxCellOptionsobjectThis option allow to set global ajax settings for the cell editiing when we save the data to the server. Note that with this option is possible to overwrite all current ajax setting in the save request including the complete event.empty object

Events

These events are related to cell editing and should be used in grid options.

Many of the following events use the parameters defined here:

  • rowid - is the id of the row
  • cellname is the name of the cell (name from colModel)
  • value - the value of the cell
  • iRow - the index of the row (do not mix with rowid)
  • iCol - the index of the column
EventParametersDescription
afterEditCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event fires after the edited cell is edited - i.e. after the element is inserted into the DOM
afterSaveCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event fires after the cell has been successfully saved. This is the ideal place to change other content.
afterSubmitCellserverresponse, rowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event Fires after the cell and other data is posted to the server Should return array of type [success(boolean),message] when return [true,“”] all is ok and the cellcontent is saved [false,“Error message”] then a dialog appears with the “Error message” and the cell content is not saved. servereresponse is the response from the server. To use this we should use serverresponse.responseText to obtain the text message from the server.
beforeEditCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event fires before editing the cell.
beforeSaveCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event fires before validation of values if any. This event can return the new value which value can replace the edited one
beforeSaveCell : function(rowid,celname,value,iRow,iCol) {
if( some_condition )
{ return “new value”; }
}
The value will be replaced with “new value”
beforeSubmitCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event fires before submit the cell content to the server (valid only if cellsubmit : 'remote'). Can return new array that will be posted to the server.
beforeSubmitCell : function(rowid,celname,value,iRow,iCol) {
if( some_condition ) {
return {name1:value1,name2:value2}
}
else
{ return {} }
}
The returned array will be added to the cellurl posted data.
errorCellserverresponse, statusfires if there is a server error; servereresponse is the response from the server. To use this we should apply serverresponse.responseText to obtain the text message from the server. status is the status of the error. If not set a modal dialog apper.
formatCellrowid, cellname, value, iRow, iColapplies only to a cell that is editable; this event allows formatting the cell content before editing, and returns the formatted value
onSelectCellrowid, celname, value, iRow, iColapplies only to cells that are not editable; fires after the cell is selected
serializeCellDatapostdataIf set this event can serialize the data passed to the ajax request when we save a cell. The function should return the serialized data. This event can be used when a custom data should be passed to the server - e.g - JSON string, XML string and etc. To this event is passed the data which will be posted to the server

Below is the order of which the events are called when the cellsubmit option is 'remote'

if a cell is editable then
1. formatCell - format and the value of the cell can be changed before editing
2. beforeEditCell
3. afterEditCell - after the input element is created
4. beforeSaveCell
5. beforeSubmitCell
if the submit is successfully
6. afterSubmitCell
7. afterSaveCell
else
6. errorCell
else if the cell is not editable
1. onSelectCell

If the cellsubmit is 'clientArray' then
if a cell is editable then
1. formatCell - format and the value of the cell can be changed before editing
2. beforeEditCell
3. afterEditCell - after the input element is created
4. beforeSaveCell
5. beforeSubmitCell
6. afterSaveCell
else if the cell is not editable
1. onSelectCell

Methods

All of the methods below should be applied to the jqGrid object and all of them return the same object.

MethodParametersDescription
editCelliRow, iCol, editedit a cell with the row index iRow( do not mix with rowid) in index column iCol. If the edit is set to false the cell is just selected and not edited. If set to true the cell is selected and edited.
getChangedCellsmethodReturns an array of the changed cells depending on method (string, default 'all'). When 'all' this method returns all the changed rows; when 'dirty' returns only the changed cells with the id of the row
restoreCelliRow, iColrestores the edited content of cell with the row index iRow( do not mix with rowid) in index column iCol
saveCelliRow, iColsaves the cell with the row index iRow( do not mix with rowid) in index column iCol

Notes

How is the data organized

When the cell is edited and the input elements is created we set the following rules:

  • The id of the editable cell element is constructed as 'iRow_'+ the name from the colModel array - where the iRow is the index of the row (not rowid) Example if we edit cell with index=20 and editable element has name 'myname' (from colModel) then the id becomes 20_myname.
  • The name of the editable element is constructed from the name of the colModel array - property - name

What is posted to the server?

When the data is posted to the server we construct object {} that contain:

  • the name:value pair where the name is the name of the input element represented in the cell
  • additionally we add a pair id:rowid where the rowid is the id of the row
  • if the returned data from beforeSubmitCell event is not empty we extend this data with the posted data.

Discussion

lgdp, 2011/03/11 06:16

jqGrid cell edit is one large bug. Never use it. It is absolutely unfriednly to addRowData and delRowData methods. Cells just become unselectable…

David Paigen, 2011/07/08 15:16

I want to process new data on the server and hand back something slightly different, e.g. expanding abbreviation: 'django has an orm' becomes 'django has an object request manager'.

I tried adding a js function as afterSubmitCell where I check the return status from the server, but it only partly works. jqGrid.restoreCell works fine if there is a server failure, but calling jqGrid.setCell from inside afterSubmitCell apparently leads to some kind of recursion bug. I either get an explicit recursion error or a notification that 's' is undefined on line 206.

Any suggestions?

Tom St.Louis, 2011/09/01 17:46

I have read all the documentation regarding jqGrid cell editing and I've yet to see an example making use of the cell events afterEditCell, beforeSaveCell, beforeSubmitCell. I'm using a treegrid with the adjacency model and in setting up the grid seem to be controlling what rows and cell I actually want to make editable. I have yet to figure out or stumble on an example using the above grid options that works. In my case, I change the cell data and hit enter and get error: e is undefined. I would guess e is the event but I'm not sure where this is falling apart. Any help you can provide is appreciated. Thanks

<cfimport prefix=“dcs” taglib=”../../tags”>

<table id=“section_174_exp_treegrid” class=“scroll”><tbody><tr><td></td></tr></tbody></table> <div id=“section_174_exp_treegrid_pager”></div> <br>

<script type=“text/javascript”>

  var qr_expense;
  function delete174Expense(id) {
      $("#section_174_exp_treegrid").jqGrid('setSelection',id);
      var local_acct = id;
      var subtdc_acct = $("#section_174_exp_treegrid").getCell(id, 'parent');
      alert('delete174Expense ' + id);
      $.ajax({
    	    type: 'POST',
    	        url: "<dcs:docroot/>services/qre_expense.cfc?method=deleteSection174Expense",
    	        async: false,
    	        data: {
    	            leid      : $("#leid").val(),
    	            cdrno     : $("#cdrno").val(),
    	            tax_year  : $("#tax_year").val(),
    	            bsla_code : $("#bsla_code").val(),
    	            reporting_period : $("#reporting_period").val(),
    	            filing_group : $("#filing_group").val(),
    	            scenario : $("#scenario").val(),
    	            subtdc_acct : subtdc_acct,
    	            local_acct : local_acct,
    	            user_id : "TEST"
    	        },
    	        success: function(data, textStatus, xhr) {
    	            //if (GIT.SSO.isExpired(xhr)) return;
    	            DCS.growl.ok(data);
   	        },
    	        error: function(data, textStatus, xhr) {
    	            DCS.growl.error(data.responseText);
    	        },
    	        dataType: 'text'
    	});
      //$("#section_174_exp_treegrid").trigger("reloadGrid");
  }
  
  function save174Expense(id) {
      $("#section_174_exp_treegrid").jqGrid('setSelection',id);
      var record = $("#section_174_exp_treegrid").jqGrid('getInd',id,true);
      //var record = $("#section_174_exp_treegrid").jqGrid('getRowData',id);
      alert('this record: ' + record.id);
      var node = $("#section_174_exp_treegrid").jqGrid('getNodeParent',record);
      alert('node parent: ' + node.id);
      var local_acct = id;
      var subtdc_acct = $("#section_174_exp_treegrid").getCell(id, 'parent');
  	//alert('after save174Expense - ' + id + '   subgrid_id - ' + subgrid_id);
  	var amount = document.getElementById(id+'_s174_amt').value;
      $.ajax({
    	    type: 'POST',
    	        url: "<dcs:docroot/>services/qre_expense.cfc?method=saveSection174Expense",
    	        async: false,
    	        data: {
    	            leid      : $("#leid").val(),
    	            cdrno     : $("#cdrno").val(),
    	            tax_year  : $("#tax_year").val(),
    	            bsla_code : $("#bsla_code").val(),
    	            reporting_period : $("#reporting_period").val(),
    	            scenario : $("#scenario").val(),
    	            subtdc_acct : subtdc_acct,
    	            local_acct : local_acct,
    	            amount : amount,
    	            user_id : "TEST"
    	        },
    	        success: function(data, textStatus, xhr) {
    	            //if (GIT.SSO.isExpired(xhr)) return;
    	            $("#section_174_exp_treegrid").jqGrid('delTreeNode',node);
    	            $("#section_174_exp_treegrid").jqGrid('expandNode',node);
    	            DCS.growl.ok(data);
   	        },
    	        error: function(data, textStatus, xhr) {
    	            DCS.growl.error(data.responseText);
    	        },
    	        dataType: 'text'
    	});		  					  
	//$("#section_174_exp_treegrid").trigger("reloadGrid");
  }
      
  function myfunction(elem) {
  	return false;
  	//alert('myfunction');
      //$(elem).afterEditCell : function(rowid, cellname, value, irow, icol){
      //                            alert('aftercelledit: ' + cellname);
      //                        } 
      }
     var MAX_DUMP_DEPTH = 10;
    
     function dumpObj(obj, name, indent, depth) {
            if (depth > MAX_DUMP_DEPTH) {
                   return indent + name + ": <Maximum Depth Reached>\n";
            }
            if (typeof obj == "object") {
                   var child = null;
                   var output = indent + name + "\n";
                   indent += "\t";
                   for (var item in obj)
                   {
                         try {
                                child = obj[item];
                         } catch (e) {
                                child = "<Unable to Evaluate>";
                         }
                         if (typeof child == "object") {
                                output += dumpObj(child, item, indent, depth + 1);
                         } else {
                                output += indent + item + ": " + child + "\n";
                         }
                   }
                   return output;
            } else {
                   return obj;
            }
     }

    var lastsel = -1;
    $(document).ready(function() {    	 	    	        
      var lastinstancesel;
      var cnt = 0;        
      
      $("#section_174_exp_treegrid").jqGrid({
   		postData: get174ExpenseFilter(),
          url: "<dcs:docroot/>cfcs/grid/Section_174.cfc?method=get174ExpenseTree&pagesize=25&returnFormat=plain",
          treeGrid: true,
          treeGridModel: 'adjacency',
          ExpandColumn: 'id',
          ExpandColClick: true,            
          sortname: 'id',
          sortorder: 'asc',
          datatype: "json",
          mtype: "GET",
          colNames: ['Account',
                     'Description',
                     'Book Amount',
                     '174 Expense',
                     'Perm Adj',
                     'Temp Adj',
                     'Tax Amount',
                     'Level',
                     'Parent',
                     'Is Leaf',
                     'Expanded',
                     'Actions'],
          colModel:[
              {name:'id', index:'id', width:80, editable:false, key:true},
              {name:'descrip', index:'descrip', width:72, editable:false},
              {name:'book_amt', index:'book_amt',  width:44, align:"right", editable:false, formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$ "}},
              {name:'s174_amt', index:'s174_amt',  width:44, align:"right", editable:true, edittype:'text'},
              	// formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$ "}},
              {name:'perm_adj', index:'perm_adj',  width:44, align:"right", editable:false, formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$ "}},
              {name:'temp_adj', index:'temp_adj',  width:44, align:"right", editable:false, formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$ "}},
              {name:'tax_amt', index:'tax_amt',  width:50, align:"right", editable:false, formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$ "}},
              {name:'level', index:'level', hidden:true, editable:false},
              {name:'parent', index:'parent', hidden:true, editable:false},
              {name:'isleaf', index:'isleaf', hidden:true, editable:false},
              {name:'expanded', index:'expanded', hidden:true, editable:false},
              {name:'act',index:'act', width:28, editable:false, sortable:false}
          ],
          pager: "#section_174_exp_treegrid_pager",
          height: "auto",
          //celledit: true, 	 
          //cellsubmit: "remote",
          //cellurl: "<dcs:docroot/>services/qre_expense.cfc?method=saveSection174Expense",
          beforeSubmitCell : function(rowid,cellname,value,iRow,iCol) { 
              alert('beforeSubmitCell: ' + cellname);
          },
          caption: 'Section 174 Expenses',
          gridComplete: function(){ 
            var ids = $("#section_174_exp_treegrid").jqGrid('getDataIDs');
	      for(var i=0;i < ids.length;i++){
                var cl = ids[i];	
                var ret = $("#section_174_exp_treegrid").getRowData(cl);  
                if (ret.level == 3) {
                  var delfunc = "delete174Expense(\"" + cl + "\")";
                  var savefunc = "save174Expense(\"" + cl + "\")";
                  tbl = "<table><tr>";
                  dr = "<td><span title='Delete Section 174 Expense' class='ui-icon ui-icon-trash' onclick='" + delfunc + "'>&nbsp;</span></td>";
                  //sr = "<td><span title='Save Section 174 Expense' class='ui-icon ui-icon-disk' onclick='" + savefunc + "'>&nbsp;</span></td>";
                  //tbl = tbl + dr + sr + "</tr></table>";
                  tbl = tbl + dr  + "</tr></table>";
                  $("#section_174_exp_treegrid").editRow(cl, true);
                  $("#section_174_exp_treegrid").jqGrid('setRowData',cl,{'act':tbl});
          	  } 
	      } 
		  $("#section_174_exp_treegrid").setGridWidth(945,true);
          }             
      });        
      function get174ExpenseFilter() {
          var filter = {
             leid: $("#leid").val(),
             cdr_no: $("#cdrno").val(),
             tax_year: $("#tax_year").val(),
             bsla_code: $("#bsla_code").val(),
             reporting_period: $("#reporting_period").val(),
             scenario: $("#scenario").val(),
             nodeid: '',
             parentid: '',
             n_level: 0               
          };
          return filter;
      }
                   
});   

</script>

Evan Reeves, 2011/09/20 20:09

Very subtle but important comment regarding cell editing (poached from stackoverflow [http://stackoverflow.com/questions/5311786/jqgrid-change-cell-input-to-readonly-after-grid-loaded]). This is crucial when using grid as a subgrid.

If you use cell editing jqGrid examine cells for the 'not-editable-cell' class. If you use inline editing the jqGrid rows for the 'not-editable-row', but in the inline editing mode the 'not-editable-cell' class will be ignored.

Theron, 2011/12/08 21:33

I found it useful to select automatically the contents if the input box when selecting the inline cell edit. i put this in the Grid Options:

  
 afterEditCell:function (rowid, cellname, value, iRow, iCol){
   document.getElementById(iRow+'_'+cellname).select();
   
    } 
Andres Guataquira, 2012/02/22 20:42, 2012/02/22 20:43

I realizand the jqGrid with cellEdit., But when you change some data in jqGrid need not only send the information change to the controller if no additional data … as I can. thanks

You could leave a comment if you were logged in.

QR Code
QR Code wiki:cell_editing (generated for current page)