Create a new column with sum of few other columns in jqgrid - jqgrid

I want to add a column which will contain summation of some columns.
Basically I want to convert following:
to the following:
But this has to be done dynamically i.e. I shall provide colModel id of th e columns I want the summation of.
P.S. Using 4.13.5 version of free-jqgrid.

The most easy way to implement your requirements would be the usage of jsonmap and sorttype defined as function, which returns the calculated value of the column. Additionally you would need to implement afterSetRow callback, which fixes the value after modification the row (after setRowData).
The corresponding implementation could be like in the demo. The demo defines the grid with total column, which displays the sum of amount and tax columns. The code of the demo looks as following:
var calculateTotal = function (item) {
return parseFloat(item.amount) + parseFloat(item.tax);
};
$("#list").jqGrid({
...
colModel: [
...
{ name: "amount", template: "number", ... },
{ name: "tax", template: "number", ... },
{ name: "total", width: 76, template: "number", editable: false,
jsonmap: function (item) {
return calculateTotal(item);
},
sorttype: function (cellValue, item) {
return calculateTotal(item);
}},
...
],
afterSetRow: function (options) {
var item = options.inputData;
if (item.total === undefined) {
// test is required to prevent recursion
$(this).jqGrid("setRowData", options.rowid, {
total: calculateTotal(item)
});
}
}
...
});

Related

Kendo Chart Does not show Data

Im sending my json data through controller like following:i have written the query here just to prevent making it complicated and messy :
My Controller Returning This:
public JsonResult powerConverter(string regionalManager)
foreach (DataRow dt in dt_power_conv.Rows)
{
_powerConv.turbineName.Add(dt["turbine_name"].ToString());
_powerConv.duration_hrs.Add(double.Parse(dt["duration_hrs"].ToString()));
_powerConv.abb_conv.Add(dt["abb_conv"].ToString());
_powerConv.eei_conv.Add(dt["eei_conv"].ToString());
_powerConv.leit_drive_conv.Add(dt["leit_drive_conv"].ToString());
}
return Json(_powerConv, JsonRequestBehavior.AllowGet);
}
in my view I get it with an Ajax call and simply bind my chart with it:
$.ajax({
dataType: "json",
type: "POST",
url: "#Url.Action("powerConverter","Ranking")",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ "regionalManager": tmpString }),
success: function (result) {
debugger;
$("#powerChart").kendoChart({
dataSource: {
data: result
},
chartArea: {
background: "#fcfcfc",
},
series: [{
axis: "l100km",
type: "column",
// name: "DURATION",
color: "#008080",
field: "duration_hrs",
categoryField: "turbineName"
},
],
categoryAxis: {
axisCrossingValue: [0, 20],
majorGridLines: {
visible: false
},
line: {
visible: true
},
labels: {
rotation: 340
},
},
tooltip: {
visible: true,
// majorUnit:10,
template: " #= value #"
},
});
}
});
I also posted the screen shot of my json,but still its not working,i set the categoryField and field with the exact name im getting from json but the chart shows nothing
It looks like the controller is returning two arrays, one for errorDuration and one for turbineName. Try changing the controller to return an array of objects.
You would want a review of returned json to show
[0] = { duration: 1, turbine: "a" }
[1] = { duration: 2, turbine: "b" }
[2] = { duration: 3, turbine: "c" }
In the chart the config settings for the series the field names have to match exactly the property names of the data elements, thus
field: "duration",
categoryField: "turbine",
Added
The controller code appears to be populating a list of a model class whose fields are also lists. Try updating it to return the Json for a list of objects
For quickness this example shows how using anonymous objects. Strongly typed objects are highly recommended for robustness and Visual Studio intellisense. The field names that you use in your kendo chart configuration will be "turbine_name" and "duration_hours"
// This technique copied from #Paul Rouleau answer to
// https://stackoverflow.com/questions/612689/a-generic-list-of-anonymous-class
// initialize an empty list that will contain objects having two fields
var dataForJson = new List<Tuple<string, double>>()
.Select(t => new {
turbine_name = t.Item1,
duration_hours = t.Item2 }
).ToList();
// go through data table and move data into the list
foreach (DataRow row in myDataTable.Rows)
{
dataForJson.Add (new {
turbine_name = (string)row["turbine_name"],
duration_hours = (double)row["duration_hours"]
});
}
return Json(dataForJson, JsonRequestBehavior.AllowGet);
Note, if you do further research you will find numerous other ways to convert a data table into a Json

Kendo UI Grid inline edit define custom values for min validation

I am using Kendo grid and want to validate one field's min value by another field from same record.
Meaning my data is like this :-
var courses = [{
CourseID : 1,
CourseName : "iPhone",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
},
{
CourseID : 2,
CourseName : "Android",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
}]
and I want to use MinAgeThreshold value in MinAge's validation min value, something like this:-
schema: {
model: {
id: "CourseID",
fields: {
CourseID: { editable: false, nullable: true },
StartDate: { editable: false, nullable: true },
CourseName: { editable: false, nullable: true },
MinAgeThreshold: { editable: false, nullable: true },
MinAge: { type: "number", validation: { required: true, min: MinAgeThreshold} },
MaxAge: { type: "number", validation: { required: true, min: 1} },
}
Is this possible somehow?
I tried to use in validation custom function like this
MinAge: {
type: "number",
validation: {
required: true,
minagevalidation: function (input) {
}
},
but I was not able to retrieve the values of MinAgeThreshold in minagevalidation function.
Any help would be greatly appreciated.
Regards
you can try something like given below to give the custom validation message and force the user to set value greater than the minimum value based on other input field in the same kendo grid.
MinAge: { type: "number",
validation: {
required: true,
MinAgevalidation: function (input) {
if(input.is("[name='MinAge']") &&(parseInt($("input[type='text'][name='MinAge']").val()) < parseInt($("input[type='text'][name='UnitPrice']").val()))){
input.attr("data-MinAgevalidation-msg", "MinAge should greater than MinAge threshold");
return false;
}
return true;
}
sample jsfiddle to set minimum value of one field based on other field's value .
I think I might have a solution for that kind of a problem. If you want to set the max of a field by the value of a different field you can add that to the grid edit method of your kendogrid.
var grid = $("#grid").kendoGrid({
edit: function(e){
if ( e.container.find("input[data-find='value:MinAge']).length != 0 ){
var numericTextBox = e.container.find("input[data-find='value:MinAge']).data("kendoNumericTextBox");
numericTextBox.min(e.model.MinAgeThreshold);
}
}
});
This will set the numerictTextBox of the MinAge input to min of the MinAgeThreshold that is in the dataItem of the row (model). That works with step, max, and so on as well. Edit is triggered when you enter the field. So if the initial value is 0 and your MinAgeThreshold is something else it will then switch to the MinAgeThreshold.

How to access column name dynamically in Kendo Grid template

I need to access the column name dynamically in Kendo Grid template.
Code:
$("#grid").kendoGrid({
dataSource: [
{ Quantity: 2 , Amount: 650},
{ Quantity: 0, Amount: 0 },
{ Quantity: 1, Amount: 500 },
{ Quantity: 4, Amount: 1047 }
],
sortable: true,
columns: [
{
field: "Quantity",
template: function (dataItem) {
if (dataItem.Quantity == '0') {
return "--";
} else {
return dataItem.Quantity;
}
}
},
{
field: "Amount",
template: function (dataItem) {
if (dataItem.Amount == '0') {
return "--";
} else {
return dataItem.Amount;
}
}
}
]
});
Here inside the "columns -> template", I need to access the column thru variable instead of hardcoding it. How can I do that? Because in real life I will be having dynamic columns populated into dataSource and I will construct the columns array inside the for loop. Please help.
Please access this JSBIN: http://jsbin.com/egoneWe/1/edit
From what I understand, you build the columns array using something like:
var Definition = [
{ field: "Quantity" },
{ field: "Amount" }
];
var columns = [];
$.each(Definition, function (idx, item) {
columns.push({
field : item.field,
template: function (dataItem) {
...;
}
})
});
$("#grid").kendoGrid({
dataSource: data,
sortable : true,
columns : columns
});
Right? And the problem is that you want to use the same template function for several (all) columns instead of having to rewrite many.
If so, what you can do is:
var Definition = [
{ field: "Quantity" },
{ field: "Amount" }
];
var columns = [];
$.each(Definition, function (idx, item) {
columns.push({
field : item.field,
template: function (dataItem) {
return commonTemplateFunction(dataItem, item.field);
}
})
});
What I use in the columns array (columns definition for the Grid) is a function that receives two arguments: the dataItem for the row and the field's name being edited.
Then, I define the template function as:
function commonTemplateFunction(dataItem, field) {
if (dataItem[field] == '0') {
return "--";
} else {
return dataItem[field];
}
}
And your modified code is here : http://jsbin.com/egoneWe/3/edit
So, despite I cannot guess the column name, I can do the trick using the columns initiator.

jqGrid: is it possible to selectively make cells editable?

how can I make one single cell editable out of a not editable column?
my javaScript looks like this:
$( '#grid' ).jqGrid({
// ...
cellEdit : true,
colModel : [
{ name : "id", index : "id", editable : false },
{ name : "wbs", index : "wbs", editable : false },
{ name : "value", index : "value", editable : false }
],
loadComplete : function(data) {
// ... foreach ( cell in data.rows.columns ) ...
if ( cell.shouldBeEditable ) {
jQuery('#grid').setCell(cell.row, cell.col, '', 'green', { editable : true });
}
}
// ...
}
so, after globally setting columns as not editable, I try to set them as editable locally, based on some criteria (to identify them more easily I also paint them green).
Alas, it's not working: cells become green, but when I try to click them they do not become editable.
Inspecting the selected cell with firebug reveals the edit-cell class to be correctly applied.
As a last note, it's working if I set columns as editable in the first instance.
I suggest you do it in reverse. Make the column editable, but disable the cells that you do not want to be editable. This is a function I wrote to disable cells:
// cellName is the name defined in your colModel
function disableGridCell(cellName) {
var cell = $('[name="' + cellName + '"]');
cell.css('display', 'none');
var div = $("<div>")
.css('width', '100%')
.css('height', '100%')
.css('border', '1px solid #000')
.css('background-color', '#CCC')
.text('xxxxxxxxxxxx');
cell.parent().append(div);
}
I call disableGridCell inside of my onEditFunc of my grid's editRow function:
$('#grid').jqGrid('editRow', id, keys, onEditFunc);
function onEditFunc(id) {
if (condition to disable cell) {
disableGridCell('CellName');
}
}
I found a nice workaround to the problem (thanks to Walter for getting me on the right track).
Instead of locking all the cells and selectively unlocking them in a declarative manner (which may lead to long load times), I'm declaring all the cells as editable.
Then I'm attaching a callback to afterEditCell option:
var $grid = $('#grid');
$grid.jqGrid({
// ...
afterEditCell : function(rowid, cellname, value, iRow, iCol) {
if ( shouldNotBeEditable(iRow, iCol) ) {
$grid.setCell(rowid, cellname, '', 'not-editable-cell');
$grid.restoreCell(iRow, iCol);
}
},
// ...
});
This way the cell is immediately reset to its previous value and I ensure that the callback gets called only once per not-to-be-edited cell, since the cell is made into a not-editable-cell after the first call.
colModel:[
{name:'description',index:'description', width:4, sortable: false, editable: true},
{name:'qty',index:'qty', width:1,sortable: false, editable: true},
{name:'cost',index:'cost', width:1, editable: true, sortable: false},
{name:'totalCost',index:'totalCost', width:1, sortable: false}
onCellSelect: function(rowid, iCol, cellcontent, e) {
//here it will allow editing of either qty or cost col for that rowid
//only if both cols have a numeric value already
if(iCol===1 || iCol===2) {
var rowdata = $("#projectTable").getRowData(rowid);
var itemCost = parseInt(rowdata['cost']);
var qty = parseInt(rowdata['qty']);
if(!$.isNumeric(itemCost) || !$.isNumeric(qty)) {
$("#projectTable").jqGrid('setColProp','qty',{editable: false});
$("#projectTable").jqGrid('setColProp','cost',{editable: false});
} else {
$("#projectTable").jqGrid('setColProp','qty',{editable: true});
$("#projectTable").jqGrid('setColProp','cost',{editable: true});
}
}
},

jqGrid Set Selected Rows

I have a jqgrid with multiselect true and I want to set some of rows.(I know the row ids.) How can I do that?
I mean opposite of
$("#myTable").jqGrid('getGridParam', 'selarrrow');
as like:
$("#myTable").jqGrid('setGridParam', 'selarrrow', rowArray);
You have to loop through the rowArray array and call setSelection method for every rowid from the rowArray:
var i, count, $grid = $("#myTable");
for (i = 0, count = rowArray.length; i < count; i += 1) {
$grid.jqGrid('setSelection', rowArray[i], false);
}
$.each(rowsToSelect, function(_, rowId) {
$grid.setSelection(rowId, false);
});
No much difference. Just seemed neater :)
(Pretty amazing that even now, in 2014, jqGrid doesn't persist checkboxes when paging..)
Here's the code I needed to use, with jqGrid 4.4.5, to get the checkboxes to set, after moving to a new page:
var idsOfSelectedRows = []; // list of RowIDs for rows which have been ticked
$("#tblContracts").jqGrid({
...
colModel: [
{ name: 'AddContract', width: 50, align: "center", editable: true, edittype: 'checkbox', editoptions: { value: "True:False" }, formatter: "checkbox", formatoptions: { disabled: false } },
{ name: "ContractName", search: true, width: 80, align: "center" }
],
loadComplete: function () {
for (i = 0; i < idsOfSelectedRows.length; i++) {
$(this).setCell(idsOfSelectedRows[i], 'AddContract', true);
}
},
During development, I put an "alert" in that "for" loop. I found that using "setSelection" simply stepped through my list of RowIDs, selected the row (so it would become highlighted), then moved on to the next, selecting that one instead.
It didn't ever tick any of the checkboxes.
Notice that my "setCell" function includes the name of the jqGrid column where I have a checkbox.
If you cut'n'paste this code, make sure you change this line to reflect the name of your jqGrid checkbox column.

Resources