Kendo Grid Aggregate for current page only - javascript

I am having an issue with the Kendo Grid aggregate function that I can't seem to solve.
I have a number of rows containing number values. At the bottom of the grid I want to display the sum of the rows.
This is already working as demonstrated in this fiddle:
http://jsfiddle.net/0Ly94e49/
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Products"
},
pageSize: 7,
aggregate: [{
field: "ProductName",
aggregate: "count"
}, {
field: "UnitPrice",
aggregate: "sum"
}, {
field: "UnitsOnOrder",
aggregate: "sum"
}, {
field: "UnitsInStock",
aggregate: "min"
}, {
field: "UnitsInStock",
aggregate: "max"
}]
},
sortable: true,
scrollable: false,
pageable: true,
columns: [{
field: "ProductName",
title: "Product Name",
footerTemplate: "Total Count: #=count#",
}, {
field: "UnitPrice",
title: "Unit Price"
}, {
field: "UnitsOnOrder",
title: "Units On Order",
footerTemplate: "Sum: #=sum#",
}]
});
});
The problem is that, as in the fiddle, the sum is for all of the rows on all pages. What I want is the sum of the rows on the current page only.
Any ideas how to change the fiddle to do that?
The project is in Angular, if that makes any difference.
Thank you in advance.

My achievement for this situation. I`ve written an aggregate:
dataSource: {
data: dataOfTable,
aggregate: [
{field: "field1", aggregate: "sum"},
{field: "field2", aggregate: "sum"},
{field: "field3", aggregate: "sum"}
],
pageSize: 20
},
FooterTemplate for column:
{
field: "field1",
title: 'Field1',
footerTemplate: "#=getCurrentField1()#"
}
for field2, field3, etc.:
{
field: "field2",
title: 'Field2',
footerTemplate: "#=currentField2#"
}
And function getCurrentField1:
// aggregates data on current page
var currentField1 = 0;
var currentField2 = 0;
var currentField3 = 0;
function getCurrentField1() {
var displayedData = $("#grid").data().kendoGrid.dataSource.view()
var resField1 = 0;
var resField2 = 0;
var resField3 = 0;
for (var i = 0; i <= displayedData.length; i++) {
if (displayedData[i] != undefined) {
resField1 += displayedData[i].field1;
resField2 += displayedData[i].field2;
resField3 += displayedData[i].field3;
}
}
currentField1 = resField1;
currentField2 = resField2;
currentField3 = resField3;
return currentPayAmount;
}
With dataBound pagination works improperly. Current data in footerTemplates were incorrect as binding was made after value of footerTemplates` was setted. So I add a function to first column, that evaluates all current values and set it properly.

In the end what I did was calculate the current page sum like this:
$scope.getCurrentPageSums = function () {
var pageNumber = $scope.grid.dataSource.page();
var pageSize = $scope.grid.dataSource.pageSize();
var first = pageSize * (pageNumber - 1);
var last = first + pageSize - 1;
var resAmount = 0;
var resDistance = 0;
for (var i = first; i <= last; i++) {
if (allReports[i] != undefined) {
resAmount += allReports[i].AmountToReimburse;
resDistance += allReports[i].Distance;
}
}
$scope.currentPageAmountSum = resAmount;
$scope.currentPageDistanceSum = resDistance;
}
I assign the rows returned from the server to allReports in the schema part of the datasource
Schema {
Data: function(data){
allReports = data;
}
}
Then I call getCurrentPageSums in the databound part of the datasource
dataBound: function () {
$scope.getCurrentPageSums();
}
Finally I bind to the value of currentPageSum in the footerTemplate of the relevant field
field: "Distance",
title: "Afstand",
footerTemplate: "Side: {{currentPageDistanceSum}}, total: #= sum # "

Set serverPaging to true.
pageSize: 7,
serverPaging : true,
aggregate: [{
field: "ProductName",
aggregate: "count"
}, {
field: "UnitPrice",
aggregate: "sum"
}, {
field: "UnitsOnOrder",
aggregate: "sum"
}, {
field: "UnitsInStock",
aggregate: "min"
}, {
field: "UnitsInStock",
aggregate: "max"
}]

Related

How can I refresh "footer" on Kendo Ui Grid using JQuery

I Set Kendo Ui Grid and footer,
footer will get total price,
but it always can't get last data.
hope somebody can help to fix it.
and i try $("#Grid").data("kendoGrid").refresh();
but it didn't work for me.
kendoui grid set
dataSource
var AddGriddataSource = new kendo.data.DataSource({
data: [],
schema: {
model: {
fields: {
id: 'No',
Name: { editable: false, nullable: false },
txtStockNum: { editable: false, nullable: false },
txtReturnNum: { editable: true, nullable: false },
txtPricetax: { editable: false, nullable: false },
txtPriceNum1: { editable: false, nullable: false }
}
} // end of model
}, // end of schema
aggregate: [{ field: "txtPriceNum", aggregate: "sum" }, { field: "txtPriceNum1", aggregate: "sum" }],
});
Cell
var AddGridCells = [
{ field: "Name", title: "Name", width: "20px" },
{ field: "StockNum", title: "Stock", width: "20px" },
{ field: "txtReturnNum", title: "txtReturnNum", width: "100px", template: '<input id = "Del" class="returnDel" type="button" value="▼" style="margin: -1px" /><input id="Txt_test1" class="returnTxtBox" type="textbox" value= #=txtReturnNum# style="margin: 2px" /><input id = "plus" class="returnPlus" type="button" value="▲" style="margin: -1px" />' },
{ field: "txtPrice", title: "txtPrice", width: "20px", hidden: true },
{ field: "txtPricetax", title: "txtPricetax", width: "20px", format: "{0:n3}" },
{ field: "txtPriceNum", title: "Total", width: "20px", footerTemplate: "#= kendo.toString(sum, '0.000')#", hidden: true },
{ field: "txtPriceNum1", title: "Total", width: "30px", footerTemplate: "<span id='footerPlaceholder'>#= kendo.toString(sum, '0.000')#</span>", format: "{0:n3}" },
{ command: [{ text: "X", click: DelchooseDetails }], title: " ", width: "10px" },
];
and
$("#AddGrid").kendoGrid({
dataSource: AddGriddataSource,
selectable: "row",
scrollable: false,
columns: AddGridCells,
change: numberInput,
pageable: {
buttonCount: 3,
messages: GridPageMsg
},
height: '100%',
editable: true
}).data("kendoGrid");
JQuery todo
$(document).on('click', '.returnPlus', function (e) {
if (nowStatus != 0) {
return;
}
var ds2 = $("#AddGrid").data("kendoGrid").dataSource;
var row = $(this).closest("tr"),
grid = $("#AddGrid").data("kendoGrid"),
dataItem = grid.dataItem(row);
debugger;
ds2.fetch(function () {
dataItem.txtReturnNum = dataItem.txtReturnNum - (-1);
dataItem.txtPriceNum = dataItem.txtReturnNum * dataItem.txtPrice;
dataItem.txtPriceNum1 = mulFloat(dataItem.txtReturnNum, dataItem.txtPricetax);
})
$("#AddGrid").data("kendoGrid").refresh();
return;
});
$(document).on('click', '.returnDel', function (e) {
if (nowStatus != 0) {
return;
}
var ds2 = $("#AddGrid").data("kendoGrid").dataSource;
var row = $(this).closest("tr"),
grid = $("#AddGrid").data("kendoGrid"),
dataItem = grid.dataItem(row);
debugger;
ds2.fetch(function () {
dataItem.txtReturnNum = dataItem.txtReturnNum - (1);
dataItem.txtPriceNum = dataItem.txtReturnNum * dataItem.txtPrice;
dataItem.txtPriceNum1 = mulFloat(dataItem.txtReturnNum, dataItem.txtPricetax);
})
$("#AddGrid").data("kendoGrid").refresh();
return;
});
I'm not sure If i does not described correctly,so i record video
https://imgur.com/mePv5qI
How can i do will be correct
Why are you using fetch()? It seems that you don't need it, since you're not updating data from api. You're only updating local data, right ? So remove it and change dataItem directly:
var row = $(this).closest("tr"),
grid = $("#AddGrid").data("kendoGrid"),
dataItem = grid.dataItem(row);
dataItem.txtReturnNum = dataItem.txtReturnNum - (-1);
dataItem.txtPriceNum = dataItem.txtReturnNum * dataItem.txtPrice;
dataItem.txtPriceNum1 = mulFloat(dataItem.txtReturnNum, dataItem.txtPricetax);
$("#AddGrid").data("kendoGrid").refresh();
Or
var row = $(this).closest("tr"),
grid = $("#AddGrid").data("kendoGrid"),
dataItem = grid.dataItem(row);
dataItem.set('txtReturnNum', dataItem.txtReturnNum - (-1));
dataItem.set('txtPriceNum', dataItem.txtReturnNum * dataItem.txtPrice);
dataItem.set('txtPriceNum1', mulFloat(dataItem.txtReturnNum, dataItem.txtPricetax));

Kendo Grid Automatically Fit Column Width except for Specific Column

I am looking for a way to let column(index = n) (by index number) or column(headingText = 'Address') (by column name) fill the gap on my kendo grid.
I know how to automatically fit column widths for a Kendo Grid:
<div id="example">
<div id="grid"></div>
<script>
$(document).ready(function() {
var grid = $("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
schema: {
model: {
fields: {
OrderID: {
type: "number"
},
ShipCountry: {
type: "string"
},
ShipCity: {
type: "string"
},
ShipName: {
type: "string"
},
OrderDate: {
type: "date"
},
ShippedDate: {
type: "date"
}
}
}
},
pageSize: 15
},
height: 550,
sortable: true,
resizable: true,
pageable: true,
dataBound: function() {
for (var i = 0; i < this.columns.length; i++) {
this.autoFitColumn(i);
}
},
columns: [{
field: "OrderDate",
title: "Order Date",
format: "{0:MM/dd/yyyy}"
},
{
field: "ShipCountry",
title: "Ship Country"
},
{
field: "ShipCity",
title: "Ship City"
},
{
field: "ShipName",
title: "Ship Name"
},
{
field: "ShippedDate",
title: "Shipped Date",
format: "{0:MM/dd/yyyy}"
},
{
field: "OrderID",
title: "ID"
}, {
field: "OrderDate",
title: "Order Date",
format: "{0:MM/dd/yyyy}"
},
{
field: "ShipCountry",
title: "Ship Country"
},
{
field: "ShipCity",
title: "Ship City"
},
{
field: "ShipName",
title: "Ship Name"
},
{
field: "ShippedDate",
title: "Shipped Date",
format: "{0:MM/dd/yyyy}"
},
{
field: "OrderID",
title: "ID"
}
]
});
});
</script>
</div>
<style>
#grid>table
{
table-layout: fixed;
}
</style>
I made a fiddle, but I don't know how to link in kendo grid:
https://jsfiddle.net/jp2code/p6cu5r29/2/
I could HARD CODE the column widths:
columns: [
{ field: "name", width: "200px" },
{ field: "tel", width: "10%" }, // this will set width in % , good for responsive site
{ field: "age" } // this will auto set the width of the content
],
But I'd like the grid to be more dynamic.
I can remove the empty space in a grid by leaving the autoFitColumn off of the last column:
<style>
.k-grid {
width: 700px;
}
</style>
<div id="grid1"></div>
<script>
function getMasterColumnsWidth(tbl) {
var result = 0;
tbl.children("colgroup").find("col").not(":last").each(function (idx, element) {
result += parseInt($(element).outerWidth() || 0, 10);
});
return result;
}
function adjustLastColumn() {
var grid = $("#grid1").data("kendoGrid");
var contentDiv = grid.wrapper.children(".k-grid-content");
var masterHeaderTable = grid.thead.parent();
var masterBodyTable = contentDiv.children("table");
var gridDivWidth = contentDiv.width() - kendo.support.scrollbar();
masterHeaderTable.width("");
masterBodyTable.width("");
var headerWidth = getMasterColumnsWidth(masterHeaderTable),
lastHeaderColElement = grid.thead.parent().find("col").last(),
lastDataColElement = grid.tbody.parent().children("colgroup").find("col").last(),
delta = parseInt(gridDivWidth, 10) - parseInt(headerWidth, 10);
if (delta > 0) {
delta = Math.abs(delta);
lastHeaderColElement.width(delta);
lastDataColElement.width(delta);
} else {
lastHeaderColElement.width(0);
lastDataColElement.width(0);
}
contentDiv.scrollLeft(contentDiv.scrollLeft() - 1);
contentDiv.scrollLeft(contentDiv.scrollLeft() + 1);
}
$("#grid1").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Employees"
},
pageSize: 6,
serverPaging: true,
serverSorting: true
},
height: 430,
pageable: true,
resizable: true,
columnResize: adjustLastColumn,
dataBound: adjustLastColumn,
columns: [{
field: "FirstName",
title: "First Name",
width: "100px"
}, {
field: "LastName",
title: "Last Name",
width: "150px"
}, {
field: "Country",
width: "100px"
}, {
field: "City",
width: "100px"
}, {
field: "Title",
width: "200px"
}, {
template: " "
}]
});
</script>
But, I don't want to always leave the last column super wide to fill the page.
I am looking for a more generic example showing how to let column(index = n) or column(headingText = 'Address') be the column that fills the gap.
I did it! Sharing with others:
function refreshGridColumns(grid, skipField) {
var index = -1;
console.log('refreshGridColumns: grid.columns.length = ' + grid.columns.length);
var columns = grid.options.columns;
// find address column and do not autofit it so that the grid fills the page
for (var i = 0; i < grid.columns.length; i++) {
if (0 < columns.length) {
console.log('refreshGridColumns: field = ' + columns[i].field);
if (columns[i].field == skipField) { // columns[i].title -- You can also use title property here but for this you have to assign title for all columns
index = i;
} else {
grid.autoFitColumn(i);
}
} else {
grid.autoFitColumn(i);
}
console.log('refreshGridColumns: i = ' + i);
}
console.log('refreshGridColumns: index = ' + index);
}
Kudos to Jayesh Goyani for this answer:
https://stackoverflow.com/a/34349747/153923

how to show sum groupFooterTemplate in kendo grid UI

I have data and showing in kendo grid with group. Every group (Invoice No - VGBEL ) has a groupFooterTemplate but Quantity (LFIMG) column always 0,00. I need sum of Quantity every footer. Where is my mistake ? I searched on the internet but didnt find solution. I know there is a little mistake but I didnt find it.
This my JS code.
var kendoResource = getKendoResourceOptions();
options.columns[0].groupFooterTemplate = 'Sipariş Toplamı:';
options.columns[8].groupFooterTemplate = '#: data.LFIMG ? kendo.format("{0:C2}",data.LFIMG.sum): 0,00 #';
$("#grid").kendoGrid({
toolbar: [{ name: "excel", text: kendoResource.toolbar.messages.excel }],
excel: {
fileName: "DeliveryList.xlsx",
allPages: true,
filterable: true
},
groupable: kendoResource.groupable,
scrollable: true,
sortable: true,
pageable: kendoResource.pageable,
columns: options.columns
});
self.filterClick = function () {
showLoading();
mbisPost('Reports.Summary', "/api/TermoTeknikReportApi/DeliveryList", ko.toJS(self.filters), function (result) {
if (result && result.length > 0) {
self.showNoDataToDisplay(false);
var dataSource = new kendo.data.DataSource({
data: result,
pageSize: 100,
group: {
field: "VGBEL",
},
aggregate: [
{ field: "LFIMG", aggregate: "sum" }
]
});
var grid = $("#grid").data("kendoGrid");
grid.setDataSource(dataSource);
// element for which the tooltip is shown
grid.thead.kendoTooltip({
filter: "th",
content: function (e) {
var target = e.target;
return $(target).text();
}
});
}
else {
self.showNoDataToDisplay(true);
}
}).error(function () { hideLoading(); }).done(function () { hideLoading(); });
}
Screenshot of webpage
I changed dataSource code. put the "aggregates" properties into the group
var dataSource = new kendo.data.DataSource({
data: result,
pageSize: 100,
group: {
field: "VGBEL",
aggregates: [ { field: "LFIMG", aggregate: "sum" },{ field: "LFIMG_M", aggregate: "sum" }] // this line
},
aggregate: [
{ field: "LFIMG", aggregate: "sum" },{ field: "LFIMG_M", aggregate: "sum" }
]
});

Kendo UI grid aggregation "sum" not working

I exactly followed the examples on Kendo UI's website. All data shows fine, but all the operation of "sum" not happening. So in the groupFooterTemplate, all columns shows the last item in the grid including the "average" column. I have been working on this for a few days and just cannot figure out what went wrong.
Did this happen to anyone?
$scope.vmResyncGridOptions = {
dataSource: {
data: $scope.vmDataSource,
scheme: {
model: {
id: "vmName",
fields: {
vmName: { type: "string" },
vdiskName: { type: "string" },
total: { type: "number" },
synced: { type: "number" },
percent: { type: "number" }
}
}
},
group: {
field: "vmName",
aggregates: [
{ field: "vdiskName", aggregate: "count" },
{ field: "total", aggregate: "sum" },
{ field: "synced", aggregate: "sum" },
{ field: "percent", aggregate: "average" }
]
},
aggregate: [
{ field: "vdiskName", aggregate: "count" },
{ field: "total", aggregate: "sum" },
{ field: "synced", aggregate: "sum" },
{ field: "percent", aggregate: "average" }
]
},
sortable: false,
scrollable: true,
pageable: true,
groupable: true,
//height: ($scope.screenHeight-110)*0.70-8,
columns: [
{
field: "vdiskName",
title: $scope.translation.Resync_Table_VDisk_Name,
aggregates: ["count"],
groupFooterTemplate: "Count: #=count#"
},
{
field: "total",
title: $scope.translation.Resync_Table_Total_Bytes,
aggregates: ["sum"],
groupFooterTemplate: "Total: #=sum#"
},
{
field: "synced",
title: $scope.translation.Resync_Table_Has_Resynced,
aggregates: ["sum"],
groupFooterTemplate: "Total Resynced: #=sum#"
},
{
field: "percent",
title: $scope.translation.Resync_Table_VDisck_Completed,
aggregates: ["average"],
groupFooterTemplate: "Percent: #=average#"
}
]
};
Initially check all the table data. There is a possibility of spaces or newline characters in the table columns. Even if the columns, which are not aggregated. After the changes recheck the solution.
You group by the same column as the datasource id:
id: "vmName",
fields: {
vmName: { type: "string" },
vdiskName: { type: "string" },
total: { type: "number" },
synced: { type: "number" },
percent: { type: "number" }
}
}
},
group: {
field: "vmName",
Thats why you don't get sum and averages.
The issue here is that the data is only cast according to the datasource schema (i.e. type: "number") during transport operations. In your case, I'm assuming you're applying the data directly using the Datasource.data([array]) method. When you apply the data yourself, the datatypes in your supplied array are preserved. So, if you pass a numberic value as a string, it will remain as a string in the datasource despite the model indicating that it should be a number. Numeric data that is cast as a string will not sum; only the last value will be returned. Look at the data you're trying to sum; see what datatype it is within the datasource. My guess is that if you're only seeing the last value then your datatype is a string.

How to make a cell in a jqxGrid dynamically editable depending on the content of the row

I am trying to make a cell in a jqxGrid editable depending on the value of another column in the row (with the name Editable).
{ text: "Percentage", datafield: "Percentage", columntype: 'numberinput', width: 100, cellsformat: 'p2',
editable: function (index, datafield, value, defaultvalue, column, rowdata) {
return rowdata.Editable;
}
},
This does not work. The cell is always editable regardless of the value of rowdata.Editable.
Replacing return rowData.Editable; with return false; does not work either.
I am using jqWidgets 3.9.0 in combination with JQuery 1.7.1.
Can anybody explain why this does not work and how to get it to work?
I got this to work by doing the following:
Replacing the url in the data source with localdata which references a local array called "data".
This array is filled using the original source url.
var data = [{}];
var source =
{
datatype: "json",
datafields: [
{ name: 'Id', type: 'number' },
{ name: 'Name', type: 'string' },
{ name: 'Percentage', type: 'string' },
{ name: 'Editable', type: 'bool' }
],
localdata: data
}
Using the cellbeginedit property instead of the editable property when defining the columns in the jqxGrid:
var dataAdapter = new $.jqx.dataAdapter(source);
$("#myGrid").jqxGrid(
{
width: 800,
source: dataAdapter,
editable: true,
editmode: 'click',
selectionmode: 'singlecell',
columns: [
{ text: "Id", datafield: "Id", columntype: 'textbox', editable: false, hidden: true },
{ text: "Name", datafield: "Name", columntype: 'textbox', width: 400, editable: false },
{ text: "Percentage", datafield: "Percentage", columntype: 'numberinput', width: 100, cellsformat: 'p2',
cellbeginedit: function (row) {
return data[row].Editable;
}
},
]
});
I was using the cellclick to do this kind of control.
$("#jqxGrid").on('cellclick', function (event) {
var args = event.args;
var datafield = event.args.datafield;
var rowIndex = args.rowindex;
var data = $('#jqxGrid').jqxGrid('getrowdata', rowIndex);
if(datafield == 'assign'){
if(data.assign){
$('#jqxGrid').jqxGrid('setcolumnproperty', 'datafield', 'editable', true);
}else{
$('#jqxGrid').jqxGrid('setcolumnproperty', 'datafield', 'editable', false);
}
}
});

Categories

Resources