Working with grids where there is column, which depends from another one, is common situation. So I try to make detailed answer on your question.
First of all you can implement your requirement in the following simple way: you can use aftersavefunc
option of editRow to make some custom actions after the row have been modified. For example you can recalculate new value for "TotalMarks"
column and explicitly call setRowData
with {TotalMarks: newValue}
as parameter.
On the other side it's good in general to use custom formatter on "TotalMarks"
column to make "virtual" column which value is not in the source data, but which value will be just calculated based on the value of other columns. In the case you need just define the corresponding custom formatter and, if you use local datatype, define custom sorttype
(see the answer, this one and this one). If you use editing of data then you should don't forget to define unformat
(unformatter function).
The following demo demonstrates the approach. It have "total"
column which content calculated as the sum of content of "amount"
and "tax"
columns. The input data don't contains any value for "total"
column. The column "total"
is editable, but because of editoptions: { disabled: "disabled" }
option the user can't change the value directly:

The corresponding definition of the "total"
is
{ name: "total", width: 60, template: numberTemplate,
sorttype: function (cellValue, rowObject) {
return parseFloat(rowObject.amount) + parseFloat(rowObject.tax);
},
formatter: function (cellValue, options, rowObject) {
var total = parseFloat(rowObject.amount) + parseFloat(rowObject.tax);
return $.fn.fmatter.call(this, "currency", total, options);
},
unformat: function (cellValue, options, cell) {
// make copy of options
var opt = $.extend(true, {}, options);
// change opt.colModel to corresponds formatter: "currency"
opt.colModel.formatter = "currency";
delete opt.colModel.unformat;
// unformat corresponds to formatter "currency"
return $.unformat.call(this, cell, opt);
},
editoptions: { disabled: "disabled" } }
By the way, I used the following code of onSelectRow
to implement inline editing:
onSelectRow: function (rowid) {
var $self = $(this),
// savedRows array is not empty if some row is in inline editing mode
savedRows = $self.jqGrid("getGridParam", "savedRow");
if (savedRows.length > 0) {
$self.jqGrid("restoreRow", savedRows[0].id);
}
$self.jqGrid("editRow", rowid, { keys: true });
}
How one can see the code don't use any lastSel
variable like in the well known code example. It could be practical in case of usage multiple editable grids on one HTML page.
If one don't want to make the column "total"
editable at all one can use aftersavefunc
to force recalculation of the total
:
onSelectRow: function (rowid) {
var $self = $(this),
// savedRows array is not empty if some row is in inline editing mode
savedRows = $self.jqGrid("getGridParam", "savedRow");
if (savedRows.length > 0) {
// cancel editing of the previous selected row if it was in editing state.
// jqGrid hold intern savedRow array inside of jqGrid object,
// so it is safe to call restoreRow method with any id parameter
// if jqGrid not in editing state
$self.jqGrid("restoreRow", savedRows[0].id);
}
$self.jqGrid("editRow", rowid, {
keys: true,
aftersavefunc: function (rowid) {
var $this = $(this),
rowObject = $this.jqGrid("getGridParam", "datatype") === "local" ?
$this.jqGrid("getLocalRow", rowid) :
{
amount: $this.jqGrid("getCell", rowid, "amount"),
tax: $this.jqGrid("getCell", rowid, "tax")
};
// one ca call setRowData below with two properties
// only which are required for
$this.jqGrid("setRowData", rowid, {
amount: rowObject.amount,
tax: rowObject.tax,
total: "dummy"
});
}
});
}
The column "total"
has editable: false
property instead of editoptions: { disabled: "disabled" }
and the editing looks more comfortable
