Row sum should calculated if price or quantity is changed.
Formatter is created according to How to access other row data from a cell's custom formatter in JqGrid
In inline and row editing modes row sum doesnt change.
Row sum column is read only and does not have id assigned. So it is difficult to create script to change it.
How to fix this so that row sum is calculated on edit ?
Testcase is in http://jsfiddle.net/ex6158L1/4/ containing
javascript
var serverResponse = {
"page": "1",
"records": "3",
"rows": [
{ "Id": "1", Quantity:4, Price : 23.33 },
{ "Id": "2", Quantity:4.55, Price : 76.66 }
]
},
$grid = $("#categorysummary");
function sumFmatter (cellvalue, options, rowObject) {
return options.rowData.Quantity *
options.rowData.Price;
}
$grid.jqGrid({
url: "/echo/json/", // use JSFiddle echo service
datatype: "json",
mtype: "POST", // needed for JSFiddle echo service
pager: '#pager',
postData: {
json: JSON.stringify(serverResponse) // needed for JSFiddle echo service
},
//colNames: ["Quantity", "Price"],
colModel: [
{ name: 'Id', hidden: true },
{ name: 'Quantity', editable: true},
{ name: 'Price', editable: true },
{ name: "Sum", formatter: sumFmatter, editable: "readonly" }
],
jsonReader: {
id: 'Id',
repeatitems: false
},
sortname: 'Id',
viewrecords: true
})
.jqGrid("navGrid",'#pager')
.jqGrid("inlineNav",'#pager');
and css
<div class="container">
<div id="pager"></div>
<table id="categorysummary"></table>
</div>
The first problem, which you have, is the bug in free jqGrid, which follows that options.rowData was not filled inside of setRowData. I posted the corresponding fix to GitHub to eliminate the problem.
The next problem is the requirement to reformat the data of editable: "readonly". Form editing do this, but not inline editing. One can use either editable: "hidden" or to add the option
inlineEditing: {
extraparam: { Sum: "" }
}
which extend the results of inline editing with the dummy value "" for Sum column. It force reformatting of the value in the Sum column.
I would recommend you additionally to change the formatter sumFmatter which you use to
function sumFmatter (cellvalue, options, rowObject) {
var quantity = parseFloat(options.rowData.Quantity || 0),
price = parseFloat(options.rowData.Price || 0);
return (quantity * price).toFixed(2);
}
see the demo http://jsfiddle.net/OlegKi/ex6158L1/7/ or to
function sumFmatter (cellvalue, options, rowObject, action) {
var quantity = parseFloat(options.rowData.Quantity || 0),
price = parseFloat(options.rowData.Price || 0);
return $.fn.fmatter.call(this, "number", quantity * price,
options, rowObject, action);
}
where I called formatter: "number" to format the results of the multiplication (quantity * price).
See the resulting demo http://jsfiddle.net/OlegKi/ex6158L1/10/
Related
What I'm trying to do is store some data in a specific column that is calculated by using the data from another column.
I currently have a function that returns the number of available licenses for the given Id in JSON
function getAvailableLicenses(id) {
var url = "/Host/Organization/AvailableLicenses/" + id;
$.get(url, function (data) {
return data.AvailableLicenses;
});
}
How do I go about storing this number in a column named "AvailableLicenses"?
Here is my current Grid:
$("#OrganizationGrid").kendoGrid({
dataSource: viewModel.get("orgDataSource"),
filterable: {
extra: false
},
sortable: true,
pageable: true,
columns: [
{ field: "Id", hidden: true },
{ field: "Name", template: "<a href='/Host/Organization/Detail/#:Id#'>#:Name#</a>" },
{ field: "LicenseNumber", title: "Number of Licenses" },
{ field: null, title: "Available Licenses", template: "#= getAvailableLicenses(Id) #" },
{ field: "LicenseExpiration", title: "License Expiration", format: "{0:MM/dd/yyyy}" },
{ field: "State" },
{ field: "Active" }
],
editable: false
});
As you can see, I tried to create a null column with a template that calls the function for the given Id.
By using Fiddler I can see that the function is indeed being called for all of the rows, but the AvailableLicenses column just displays Undefined for every row.
Is there something I'm missing here to get this to work?
I think the better way to do this is on dataSource parse() function
First: you column configuration must change like this:
{ field: "AvalableLicenses", title: "Available Licenses" },
You alaways can use you template .
And second, inside your dataSource() you can add:
schema: {
parse: function(response) {
for (var i = 0; i < response.length; i++) {
response[i].AvalableLicenses= null;
response[i].AvalableLicenses = getAvailableLicenses(response[i].Id)
}
return response;
}
}
EDIT:
If you prefer using you way, I dont see any problem in your configuration, probably your $.get is returning undefined, or something you don't expect.
For conviniance I did an example working.
http://jsfiddle.net/jwocf897/
Hope this help
Trying to sort a grid with custom sort. I am building jqgrid with dynamic columns and data. Everything works well except sorting of one of the column. I am using javax.json to build the json and I am using jqgrid 4.7.0. Here is the grid code:
var resultsGrid = $("#resultsGrid");
var url = "grid/GridDataController?action=runSearch&searchText="+getSearchText()+"&_ts"+$.now();
var csvUrl = "grid/GridDataController?action=downloadCsv&_ts"+$.now();
var gridPagerId="#resultsPager";
var drawSearchResultsGrid = function(colNames,colModel,data) {
resultsGrid.disableSelection(); //disales highlioghting cells outside selection like ghosting.
resultsGrid.jqGrid({
url: url,
datatype: 'jsonstring',
loadonce: true,
mtype: "GET",
height: 300,
width: 700,
colNames: colNames,
colModel: colModel,
datastr : data,
rowNum: 100000,
sortname: "invid",
sortorder: "asc",
rownumbers: true,
viewrecords: true,
pager: gridPagerId,
pginput : false,
pgbuttons : false,
viewrecords : false,
gridview: true,
autoencode: true,
onSelectRow : function(id) {
logMessage("row selected ["+id+"]");
},
loadComplete: function(data) {
logMessage("load completed");
},
ondblClickRow : function(rowid) {
logMessage("Double clicked");
$(escapeColon("#contentForm:viewPropertiesButton")).click();
}
});
// Set navigator with search enabled.
resultsGrid.jqGrid('navGrid',gridPagerId,{add:false,edit:false,del:false,search:false,refresh:false});
// add custom button to export the data to excel
resultsGrid.jqGrid('navButtonAdd',gridPagerId,{
caption:"Export",
onClickButton : function () {
resultsGrid.jqGrid('excelExport',{"url":csvUrl});
}
});
}; //end drawResultGrid function
//get grid config...
$.ajax({
type: "GET",
url: url,
data: "",
dataType: "json",
success: function(response)
{
if (response.result == "0")
{
logMessage("Drawing results grid...");
drawSearchResultsGrid(response.colNames,response.colModel,response.data);
resizeGrid();
logMessage("Results grid drawing done.");
}
else
{
logMessage("Error : " + response.message);
alert(response.message);
}
},
error: function(x, e)
{
alert(x.readyState + " "+ x.status +" "+ e.msg);
}
});
Here is my dynamic colModel looks like:
{
"result":"0",
"message":"",
"data":{
"records":18,
"total":1,
"page":"1",
"rows":[ ]
},
"colNames":[
"IP Address/Cidr",
"Name",
"IP Decimal",
"Cidr"
],
"colModel":[
{
"name":"adressCidr",
"width":50,
"sortable":true,
"hidden":false,
"sorttype":"function (cellValue,rowObject) { console.log('sorting by ['+rowObject.ipDecimal+']'); return parseInt(rowObject.ipDecimal,10);}"
},
{
"name":"name",
"width":50,
"sortable":true,
"hidden":false
},
{
"name":"ipDecimal",
"width":50,
"sortable":true,
"hidden":false,
"sorttype":"int"
},
{
"name":"cidr",
"width":0,
"sortable":false,
"hidden":true
}
]
}
ipDecimal is a hidden column but I am displaying it for testing purpose. Requirement is first column 'addressCidr' is a string column but i want to sort it using hidden ipDecimal column. The function neither does show console.log message nor does any sorting properly. However, If i sort by ipDecimal with sorttype as 'int' by clicking on its header, it works fine. Only thing i can think of is the double quote around the sorttype function itself. Please let me know if you see any other issue here, or what is the best way to solve this case. Here is snippet where I build json function:
private JsonObjectBuilder createColumn(JsonBuilderFactory factory,
String name,int width,boolean sortable,boolean hidden,boolean sorttype)
{
JsonObjectBuilder column =this.createColumn(factory, name, width, sortable, hidden);
StringBuilder fnBuilder = new StringBuilder("");
//this is not generic but can easily be made one :(
fnBuilder.append("function (cellValue,rowObject) {");
fnBuilder.append(" console.log('sorting by ['+rowObject.ipDecimal+']');");
fnBuilder.append(" return parseInt(rowObject.ipDecimal,10);");
fnBuilder.append("}");
column.add("sorttype", fnBuilder.toString()); // this works, not sure why above function does not work :(
return column;
}
private JsonObjectBuilder createColumn(JsonBuilderFactory factory,
String name,int width,boolean sortable,boolean hidden)
{
JsonObjectBuilder column;
column = factory.createObjectBuilder();
column.add("name", name);
column.add("width", width);
column.add("sortable", sortable);
column.add("hidden", hidden);
return column;
}
Data I used for testing is:
IpAddressCidr ipDecimal
5.1.0.0/24--83951616
5.1.1.0/24--83951872
5.1.2.0/24--83952128
5.1.3.0/24--83952384
5.1.4.0/24--83952640
5.3.0.0/24--84082688
5.9.2.0/24--84476416
6.0.0.0/24--100663296
6.0.1.0/24--100663552
6.0.2.0/24--100663808
6.0.3.0/24--100664064
6.0.4.0/24--100664320
6.0.5.0/24--100664576
7.1.0.0/24--117506048
7.1.1.0/24--117506304
7.1.2.0/24--117506560
7.1.3.0/24--117506816
198.186.198.0/24--3334129152
But here is that I see
Ip 198.186.198.0 should have appeared at the top as it has highest ipDecimal, but it gets pushed to the bottom.
To add more test information. If I remove enclosed double quotes, sort works fine, but not with it.
Following works:
{ name: "adressCidr", width:50, sortable: true,
sorttype: function (cellValue,rowObject) { console.log('sorting by ['+rowObject.ipDecimal+']');return parseInt(rowObject.ipDecimal,10);}},
Following does not:
{ name: "adressCidr", width:50, sortable: true,
sorttype: "function (cellValue,rowObject) { console.log('sorting by ['+rowObject.ipDecimal+']');return parseInt(rowObject.ipDecimal,10);}"},
The reason of your problem is the usage of sorttype which you defines as string instead of function:
{
"name":"adressCidr",
"width":50,
"sortable":true,
"hidden":false,
"sorttype":"function (cellValue,rowObject) { console.log('sorting by ['+rowObject.ipDecimal+']'); return parseInt(rowObject.ipDecimal,10);}"
}
You use jqGrid 4.7 which contains new feature which I suggested (see here). So you can include the code like
$.extend($.jgrid, {
cmTemplate: {
myIpAddress: {
sorttype: function (cellValue, rowObject) {
console.log('sorting by [' + rowObject.ipDecimal + ']');
return parseInt(rowObject.ipDecimal, 10);
},
width: 50
}
}
});
Now you can change the data returned from the server to
{
"name":"adressCidr",
"sortable":true,
"hidden":false,
"template":"myIpAddress"
}
Edit:
Okay I think it's because when I assign sumColumnModel to colModel sumColumnModel is empty because sumColumnModel is only non-empty within the success function. So is there any way I can get that variable out of the success function and use it in colModel?
I am using a function to get my data and I am getting the data out just fine. I get this JSON from data.d:
"{"Page":1,
"TotalPages":5.0,
"TotalRecords":122,
"ColumnModel": [
{"name":"Description","sorttype":"string","align":"center"},
{"name":"Matrix","sorttype":"string","align":"center"},
{"name":"AvailableReports","sorttype":"string","align":"center","hidden":true},
{"name":"Classification","sorttype":"string","align":"center","hidden":true}
],
"Submissions":[
{"DateSubmitted":"4/23/2014","DateSampled":null,"Matrix":"Sometype","Status":"Completed","SubmissionId":"001","Description":"description","Company":null,"Classification":null,"AvailableReports":7},
{"DateSubmitted":"4/23/2014","DateSampled":null,"Matrix":"sometype","Status":"Completed","SubmissionId":"002","Description":"description","Company":null,"Classification":null,"AvailableReports":6}
]}"
I am currently using this jsonreader:
jsonReader: {
repeatitems: false,
root: function(obj) { return obj.Submissions; },
page: function(obj) { return obj.Page; },
total: function(obj) { return obj.TotalPages; },
records:function(obj) { return obj.TotalRecords; },
}
I tired putting in just 'Submissions' for the value of root in jsonreader but that didnt do the trick.
My column model is being edited in the success part of my ajax function call to correctly display certain columns that is done like this.
myData.ColumnModel.splice(0, 0,
{ name: "DateSubmitted", label: "Date Submitted", sorttype: "date", align: "center"});
myData.ColumnModel.push(
{ name: "Status", sorttype: "string", align: "center" },
{ name: "SubmissionId", label:"Submission Id", sorttype: "string", align: "center" });
sumColumnModel = myData.ColumnModel;
then I pass sumColumn as the Column model for the grid.
colModel: sumColumnModel,
Any idea why the grid isn't being populated?
So I wound up just initializing the colModel and then adding/subtracting things from it based on a couple drop down menus. It would be nice to know if I could actually get the col model out of the datatype:function but at this point I've just worked around it.
I have a jqgrid with grouping, however the data coming back from the server is already grouped, I simply want to apply the jqgrid grouping look to the data. I've included a jsfiddle since a picture speaks 1000 words. THE DATA IS INCLUDED IN THE FIDDLE...
Link to fiddle : http://jsfiddle.net/Rab815/p8Zsk/
$('table').jqGrid({
data: data,
datatype: "local",
rowNum:100,
gridview: true,
deepempty: true,
hoverrows: false,
headertitles: true,
height:'600px',
viewrecords:true,
hoverrows: true,
sortable: true,
altRows: true,
colModel: [
{ label: "Group Name", name:'groupName', field:"groupName", sortable:false},
{ label: 'Name', field: 'name', name:'name' },
{
label: 'Date Modified', field: 'lastGenerated', name:'lastGenerated'
}
],
grouping:true,
groupingView:
{
groupField: ['groupName'],
groupColumnShow: [true],
groupCollapse: true,
},
shrinkToFit: false
});
However I need it displayed in this order
Now, if you put the data in an editor so each block appears on one line, the data is already coming back grouped from the DB in the order I want it to appear. but the grid is sorting the groupName data field in 'asc' order and far as I can tell it can't be turned off.
The Grouping Column would eventually be set to groupColumnShow: [false]
ANSWER from Olegs FIDDLE...
Included a
groupOrder
in the data coming from the server rather than doing the mapping.
Altered ColModel for GroupName as follows
{
label: "Group Name", field: "groupName",
sorttype: function (cellValue, obj) {
return obj.groupOrder;
//return groupOrder[obj.groupId];
}
Now everything appears in the correct order. This solution allows the sort, which defaults to "asc" in jqgrid to order the grouped data by a different value other than the grouped data itself.
Thanks! This had me stumped for quite a while!
The problem exist because you use datatype: "local" with the data loaded from the server.
To solve your problem you can define sorttype property as function in the column "groupName" by which you sort. The function should return the value which can be used instead of the column value. For example you can extend the items of the data with new field groupOrder for example and use
sorttype: function (cellValue, obj) {
return groupOrder[obj.groupId];
}
The field should be filled on the server.
Alternatively you can fill the map between groupId in your current data model and the index to the group order. For example the code
var groupOrder = {}, i, l = data.length, groupId, groupIndex = 1;
for (i = 0; i < l; i++) {
groupId = data[i].groupId;
if (groupOrder[groupId] === undefined) {
groupOrder[groupId] = groupIndex++;
}
}
fills groupOrder in the same order in which you have the groups (you can use data[i].groupName instead of data[i].groupId in the same way). Having such groupOrder you can use
sorttype: function (cellValue, obj) {
return groupOrder[obj.groupId];
}
The demo http://jsfiddle.net/p8Zsk/38/ use the approach and it displays the groups in correct order.
This is a follow-up to my earlier question posted here. I have cases where we get large amount of data, around 200KB to be displayed on the jqgrid. In such case, the last sets of data are never displayed. Each record is split by a newline character. The data is in this format:
{"data":{"data":"\tat org.aaa.aaa.aaa.aaa.aaa.aaa(aaa.java:512)[147:org.aaa.aaa.aaa:9.1.1]\n\tat aaa.aaa.aaa.aaa.aaa.aaa(aaa.java:1789)[146:org.aaa:9.1.1]\n"}}
The code for grid is as follows:
$("#grid").jqGrid({
type: "GET",
url: "/getdata",
datatype: "json",
colNames: [''],
colModel: [
{name: 'data', align: 'left', sortable: false}
],
jsonReader: {
root: "data",
cell: "",
id: function () {
return function () {
return $.jgrid.randId();
}
},
page: function() { return 1; },
total: function() { return 1; },
records: function(obj) { return obj.data.length; }
},
loadonce: false,
viewrecords: true,
sortname:'',
rowNum: '9999',
autowidth: true,
ignoreCase: true,
height: "auto",
multiselect: false,
sortable: false,
autoencode: true,
loadComplete: function() {
$("tr.jqgrow:even").css("background", "#DDDDDC");
},
// We will handle the errors with ajax error handlers for now
loadError: function(error){
displayError(error.responseText);
},
beforeProcessing: function (data) {
var items = data.data.split("\n"), i, l, item;
data.logs = [];
for (i = 0, l = items.length; i < l; i++) {
item = $.trim(items[i]);
if (item.length > 0) {
data.data.push([item]);
}
}
}
});
I tried setting the rowNum to '', 99999, nothing worked. The total number of lines wwas The same lines seem to be getting chopped from display in jqgrid. Is there any limit to the amount of data that jqgrid can display? As of now, no pagination has been implemented on jqgrid.
Any pointers are greatly appreciated.
thanks,
Asha
First of all I recommend you to use correct type of all input parameters of jqGrid. In the documentation you will find the table which has "Type" column. The type of rowNum column is integer. So you should use rowNum: 9999 instead of rowNum: '9999'.
Additionally I strictly recommend you always use gridview: true option of jqGrid. In case of placing all data on one page such setting can improve the performance of filling of the grid in many times.
In the same way I don't recommend you to make any modification of the grid inside of loadComplete. It reduce the performance of jqGrid. You can define your custom CSS class for example
.myAltRows: { background: #DDDDDC }
and use the options altRows: true, altclass: "myAltRows". Alternatively you can use rowattr callback to set custom class or custom style on selected rows of the grid. See the answer for more details.
The last remark. I don't recommend you to include options which has default values (for example, type: "GET", loadonce: false, sortname:'', multiselect: false, sortable: false) or properties of colModel having default values (for example align: 'left'). You should examine default values column of the option and colModel options of the documentation.