How to show aggregated value in ClientGroupHeaderTemplate in Kendo Grid - kendo-ui

I am using UI for ASP.NET MVC to build a grid. I want to group rows by the Name column and show sum of the Cost column in the group header.
Here is my grid
#(Html.Kendo().Grid<GridModel>()
.Name("myGrid")
.Columns(col =>
{
col.Bound(p => p.Name).Width(300);
col.Bound(p => p.Year).Width(100);
col.Bound(p => p.Cost).Width(100)
.ClientGroupHeaderTemplate("Total: #: sum #");
})
.AutoBind(true)
.DataSource(dataSource => dataSource
.Ajax()
.Aggregates(aggregates =>
{
aggregates.Add(p => p.Cost).Sum();
})
.Group(groups => groups.Add(p => p.Name))
.Read(read => read
.Action("GetData", "Home", new { ID = Model.ID }))
.ServerOperation(false))
)
The grid above does not show or render sum in group header.
The demo here shows how to do it, however it showing aggregated values in group footer. I want to show sum in group header.
In above grid if i replace ClientGroupHeaderTemplate with ClientGroupFooterTemplate then i see sum in group footer, but i want to show sum in group header.
What i am missing here
Update 1
Also as per the documentation aggregates object is available in ClientGroupHeaderTemplate which provides access to all available aggregates
aggregates - provides access to all available aggregates, e.g.
aggregates.fieldName1.sum or aggregates.fieldName2.average
so i tried
col.Bound(p => p.Cost).Width(100)
.ClientGroupHeaderTemplate("Total: #= aggregates.Cost.sum #");
but this did not work either.
It looks like ClientGroupHeaderTemplate only works if the column is a part of group.
In my case I am grouping by Name column so Cost column is not part of Group

aggregates will not work for older versions of kendo
Without grouping
Try putting this in javascript
var aggregates;
$(function(){
// get aggregates from datasource. Access to all aggregates
aggregates = $("#grid").data("kendoGrid").dataSource.aggregates();
})
Along with this in view
col.Bound(p => p.Cost).Width(100).ClientGroupHeaderTemplate("Total: #= aggregates.Cost.sum #");

Related

Using Kendo-UI grid for asp.net MVC, with multi-checkbox filtering, how do I configure data source for limiting options returned by the server?

I'm working with a Kendo-UI grid for asp.net MVC (version 2022.2.621.545) and I added multi-checkbox filtering to the columns. The grid items are pulled from the server using a configured ajax call to a controller action, and clicking on a filter button triggers another call to retrieve the full set of items in order to build the checkbox list. In some cases there are too many items returned and the grid appears to hang trying to determine the unique items for the checkbox list.
I was wondering if lazy loading can be configured for multi-checkbox filtering such that paging info is sent to the data source controller action. Alternatively, I've read that there may be a way to hold off on retrieving items for the filter until a minimal search string has been entered, with the search string being sent to the data source controller action.
I've looked at Kendo-UI documentation for multi-checkbox filtering options, but nothing has been abundantly clear that what I need to do is possible, especially within the asp.net MVC directives. I'm hoping someone can provide some guidance as to how to modify my grid setup to configure additional control for retrieving filter options. This is my current working code:
<div style="height:690px" id="warehouseGrid">
#(Html.Kendo().Grid<WarehouseModel>()
.Name("inventoryGrid")
.HtmlAttributes(new { style = "height:100%; width: 100%;" })
.Columns(columns =>
{
columns.Bound("InventoryLineItemID").Title("").Width(35).Filterable(false).ClientTemplate(
"<img src='https://cdn.host/show_detail.png' class='k-icon k-delete' height='45' width='45' onclick='ShowInventoryItemDetails(\"#= InventoryLineItemID #\")' onmouseover='' style='cursor: pointer;' title='Show Inventory Item Details' alt='Show Inventory Item Details' />"
);
foreach (WarehouseField col in fields)
{
if (!string.IsNullOrEmpty(col.Template))
{
columns.Bound(col.PropertyName).Title(col.Title).Width(col.Width).Filterable(false).ClientTemplate(col.Template);
}
else
{
columns.Bound(col.PropertyName).Title(col.Title).Width(col.Width).Filterable(ftb => ftb.Multi(true).Search(true));
}
}
})
.Pageable(pager => pager.PageSizes(new[] { 10, 20, 50, 100 }))
.Excel(excel => excel
.AllPages(true)
)
.ToolBar(
toolbar =>
{
toolbar.Template(#<text>
#ToolbarTemplate()
</text>);
}
)
.Events(e => e.DataBinding(#<text>function(e) { onDataBinding(this) }</text>))
.Events(e => e.DataBound(#<text>function(e) { onDataBound(this) }</text>))
.Resizable(r => r.Columns(true))
.ColumnResizeHandleWidth(5)
.Scrollable()
.Sortable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(100)
.Read(read => read.Action("GetInventory", "Warehouse", new { area = "Rest" }).Data("additionalData"))
)
)
</div>

How to keep the Kendo grid default grouping from being removed

I have a grid which has default grouping by one of the columns e.g "Important". I allow grouping by other columns, but I want to lock my default grouping. So no one can remove this grouping.
I didn't find any property to achieve this. I tried using the DataBound event change class and removed the remove button of this column in the group header but later the Kendo script reverted this back to its original state.
#(Html.Kendo().Grid<Model>()
.Name("Grid")
.DataSource(ds => ds
.Ajax()
.PageSize(20)
.ServerOperation(false)
.Model(m => m
.Id(z => z.Id))
.Read(r => r.Action("myAction", "myController"))
.Group(g=>g.AddDescending(c=>c.Important))
)
.Columns(c =>
{
c.Bound(d => d.Important)
.Title("This is important")
.Groupable(false)
.Visible(true)
.Hidden(true);
c.Bound(d => d.otherColumn)
.Title("otherColumn")
.Groupable(true);
....
}
.Groupable()
.Events(e=>e
.Change("onChange")
.DataBound("dataBound")
)
)

Change the title of groub column in kendo mvc grid

I have a grid , and i am grouping the data on date column like this :
.Group(g => g.Add(c => c.EmployeeId)).Group(g => g.Add(c => c.CheckInTime.Day))
and it works fine, but the problem is the title is CheckInTime.Day .
my question is how can i change this title ?
Thanks
If you have a column field that matches the group field then you can set the bound fields Title to whatever you want to display. However, I don't think you can have a different title for the column and group header.
columns.Bound(c => c.CheckInTime.Day).Width(100).Title("This will in column header and group header");
If you do not have a bound column that matches a group field then you might be able to get away with something like:
columns.Bound(c => c.CheckInTime.Day).Title("Group Title")
.HtmlAttributes(new { style = "visibility:hidden;" })
.HeaderHtmlAttributes(new { style = "visibility:hidden;" })
.ClientGroupFooterTemplate(new { style = "visibility:hidden;" })
.FooterHtmlAttributes(new { style = "visibility:hidden;" })
However, using the above hack adds a ui inconsistency on the first column. There may be a more elegant way to have a group field without a bound column display a different title using js, have not found it yet.

Kendo UI ASP.NET MVC grid datasource filters value is null

I am trying to dynamically add grid filters in my view using the html helper via datasource configuration, like this example from the kendo documentation:
#(Html.Kendo().Grid<Product>()
.Name("grid")
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Products_Read", "Home"))
.Filter(filters =>
{
if (someCondition){
// Show products whose ProductName property contains "C"
filters.Add(product => product.ProductName).Contains("C");
// and UnitsInStock is greater than 10
filters.Add(product => product.UnitsInStock).IsGreaterThan(10);
}
})
)
)
The filters are added, but the filterdescriptor.Value in each case is always null (the Member and Operator are fine).
Any help much appreciated.
Thanks!
--Berry
Make sure you have included kendo.aspnetmvc.min.js. Missing it would lead to similar symptoms.

How can I display a non aggregate model value in a Telerik MVC Grid aggregate header?

My grid:
#( Html.Telerik().Grid<eGate.BackOffice.Core.Model.UI.EgateMenuRevisionViewData>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(c => c.ParentId)
.Aggregate(a => a.Count()).ClientGroupHeaderTemplate(Html.ActionLink("Create a Revision for This Menu", "Edit", "Thing", new { menuid = "<#= Key #>" }, null).ToString());
columns.Bound(c => c.ParentName);
columns.Bound(c => c.ThingName);
})
.Groupable(grouping => grouping.Groups(groups => {
groups.Add(c => c.EgateMenu.EgateMenuId);
}).Visible(false))
This works. But it gives me:
Create a revision for this menu
1 Parent 1 Thing 1.1
1 Parent 1 Thing 1.2
1 Parent 1 Thing 1.3
Create a revision for this menu
2 Parent 2 Thing 2.1
2 Parent 2 Thing 2.2
2 Parent 2 Thing 2.3
And while that works, I'd much rather something more intuitive like:
Create a thing for parent 1
Thing 1.1
Thing 1.2
Thing 1.3
Create a thing for parent 2
Thing 2.1
Thing 2.2
Thing 2.3
Problem 1:
Create a thing for... needs to pass the ParentId to the actionlink but it needs to display the ParentName for the client yet only one exists in the aggregate at a time.
Problem 2:
I want to group by the Id without displaying the Id column in the results. But setting the column to visible(false) supresses the clientgroupheadertemplate.
Adding Visible(false) to the column binding suppresses the whole column itself from even being rendered in the client html - hence the suppression of the ClientGroupHeaderTemplate.
I would either try adding ParentId as a data key - e.g.
.DataKeys(keys =>
{
keys.Add(k => k.ParentId);
}
I think this would only help if you were using the built in grid (AJAX or Server) DataBinding though (for Insert at least). With an ActionLink however... I don't have much experience with using mvc html helpers in client templates - but if you said the orignal example worked with it, shouldn't something like this work as well?
columns.Bound(c => c.ParentId).ClientTemplate("")
.Aggregate(a => a.Count()).ClientGroupHeaderTemplate(Html.ActionLink("Create a thing for \"<#= ParentName #>\"", "Edit", "Thing", new { menuid = "<#= Key #>" }, null).ToString());
I added a blank ClientTemplate, which I assume would work so that the ID is not displayed.
Have you tried hiding the unwanted columns?
#( Html.Telerik().Grid<eGate.BackOffice.Core.Model.UI.EgateMenuRevisionViewData>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(c => c.ParentId).Visible(false);
.Aggregate(a => a.Count()).ClientGroupHeaderTemplate(Html.ActionLink("Create a Revision for This Menu", "Edit", "Thing", new { menuid = "<#= Key #>" }, null).ToString());
columns.Bound(c => c.ParentName).Visible(false);
columns.Bound(c => c.ThingName);
})
According telerik :
You can specify now Aggregate property with following values: Sum, Min, Max, Last, First, Count, Avg & Custom for every GridBoundColumn and the grid will calculate these aggregates if ShowFooter is set to true. In case of Custom aggregate the grid will raise event OnCustomAggregate where you can set desired result using e.Result.
So try First, Last or Custom options for every GridBoundColumn and set ShowFooter property to false.
<telerik:GridBoundColumn Aggregate="First" DataField="CustomerID" DataType="System.String"
HeaderText="CustomerID" SortExpression="CustomerID" UniqueName="CustomerID">
</telerik:GridBoundColumn>

Resources