Kendo grid aggregate column - c#

I'm binding a kendo grid with 12 Columns (12 months), i want a last column that will be the aggregation of all the 12 months (total of the year)..
i have this:
#(Html.Kendo().Grid<WebAnalise.Models.map_sel_fabr_prod>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.nameFabr).Visible(true).Width(50).Title("Fabr");
columns.Bound(p => p.nameProd).Width(100).Title("Prod");
columns.Bound(p => p.tot01).Width(30).Title("Jan");
columns.Bound(p => p.tot02).Width(30).Title("Fev");
columns.Bound(p => p.tot03).Width(30).Title("Mar");
columns.Bound(p => p.tot04).Width(30).Title("Abr");
columns.Bound(p => p.tot05).Width(30).Title("Mai");
columns.Bound(p => p.tot06).Width(30).Title("Jun");
columns.Bound(p => p.tot07).Width(30).Title("Jul");
columns.Bound(p => p.tot08).Width(30).Title("Ago");
columns.Bound(p => p.tot09).Width(30).Title("Set");
columns.Bound(p => p.tot10).Width(30).Title("Out");
columns.Bound(p => p.tot11).Width(30).Title("Nov");
columns.Bound(p => p.tot12).Width(30).Title("Dez");
//I want to add the new column here! Something like this, but aggregation! (tot01 + tot02 + tot03 ... + tot12)!! not only value from one column:
columns.Bound(p => p.tot01).Width(30).Title("TOT");
})
Can anyone help?

Try this
First Make sure your model columns are decimal
Add the Total Column in the end of the grid if you want to use the footer then add client footer.
Add Aggregate as shown
Add Javascript
Finally total column will sum total of given columns dynamically and will show grand total in footer as well.
**************Grid********
#(Html.Kendo().Grid<WebAnalise.Models.map_sel_fabr_prod>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.tot11).Width(30).Title("Nov");
columns.Bound(p => p.tot12).Width(30).Title("Dez");
columns.Bound(c => c.Total).Title("Total")
.ClientTemplate("#= kendo.format('{0:c}',Total) #")
.ClientFooterTemplate("<div>Grand Total: #= kendo.format('{0:c}',sum) #</div>");
}
.DataSource(dataSource => dataSource
.Ajax()
.Aggregates(aggregates =>
{
aggregates.Add(p => p.Total).Sum();
})
.PageSize(20)
.Events(events => events.Error("error_handler"))
.ServerOperation(false)
.Events(e=>e.Edit("onEdit").Save("onSave"))
)
*********Javascript*******************
function onEdit(e)
{
var indexCell = e.container.context.cellIndex;
if (typeof indexCell != "undefined") {
var input = e.container.find(".k-input");
input.blur(function () {
e.model.set("Total", (e.model.tot01 * e.model.tot02 *e.model.tot03);
});
var texbox = e.container.find(".text-box");
texbox.change(function () {
e.model.set("Total", (e.model.tot01 * e.model.tot02 *e.model.tot03);
});
}
}
function onSave(e)
{
//update the aggregate columns
var dataSource = this.dataSource;
e.model.one("change", function () {
dataSource.one("change", function () {
dataSource.aggregates().Total.sum;
});
dataSource.fetch();
});
}
Regards
Shaz

You can use the built-in aggregate functionality of the Kendo UI Grid as shown in this demo:
http://demos.telerik.com/kendo-ui/web/grid/aggregates.html
You can display the aggregate information in the footer template of the last column (shown in the demo)

Are you using LinQ or ADO for data access??? Whichever it is it doesn't really matter but you can just return the sum using your LinQ query or in your stored procedure and tie the sum to a property of your model class

Related

Telerik Mvc grid with SignalR events not firing

I have a Telerik MVC Grid bound by SignalR. I'm looking to color the records conditionally dependent on a value in a given column (EventHexCode). To do this I need to fire an event on DataBound. I have used this many times with an AJAX datasource without having any issues firing events. But for the life of me I cannot get the DataBound event to fire with a SignalR data source.
I've used this method to achieve this in the past: https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/Layout/style-rows-cells-based-on-data-item-values#iterate-the-table-rows
Here is my view:
#(Html.Kendo().Grid<DirectOrderTracker.Models.ViewModels.TempOrderViewModel>()
.Name("grid")
.ToolBar(toolBar =>
{
toolBar.Create();
// toolBar.Save();
})
.Filterable(ftb =>
{
ftb.Extra(false);
ftb.Operators(op =>
{
op.ForString(str =>
{
str.Clear().Contains("Contains");
});
});
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Events(e => { e.DataBound("onDataBound"); })
.Navigatable()
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height:650px;" })
.Columns(columns =>
{
columns.Bound(p => p.TempOrderID).Hidden();
columns.Bound(p => p.EventHexCode).ClientTemplate("<span style='display: inline-block; width: 100%; height: 100%; background-color: #= EventHexCode #'> </span>").EditorTemplateName("ColorPicker").Width(120);
columns.ForeignKey(p => p.CustCode, (System.Collections.IEnumerable)ViewData["defaultCustCode"], "CustCode", "CustDesc").Title("Customer").EditorTemplateName("CustDescAutoComplete").Width(180);
columns.Bound(p => p.PONum).Title("Our PO#").Width(90);
columns.Bound(p => p.CustRef).Title("Cust Ref#").Width(90);
columns.Bound(p => p.ApptTime).Title("Appt").Width(70).Filterable(x => x.UI(GridFilterUIRole.TimePicker));
columns.Bound(p => p.Qty).Width(65).Filterable(false);
columns.ForeignKey(p => p.ProdNum, (System.Collections.IEnumerable)ViewData["defaultProdNum"], "ProdNum", "ProdDesc").Width(130).Title("Size/Spec").EditorTemplateName("ProdNumAutoComplete");
columns.Bound(p => p.SalePrice).Format("{0:c}").Width(75).Title("Price").Filterable(false);
columns.Bound(p => p.SONum).Title("Our SO#").Width(120);
columns.Bound(p => p.DueDate).Format("{0:MM/dd/yyyy}").Width(120).Title("Due Date");
columns.Bound(p => p.LoadDate).Format("{0:MM/dd/yyyy}").Width(120).Title("Load Date");
columns.ForeignKey(p => p.VendCode, (System.Collections.IEnumerable)ViewData["defaultVendCode"], "VendCode", "VendDesc").Title("Vendor").EditorTemplateName("VendDescAutoComplete").Width(130);
columns.Bound(p => p.Cost).Format("{0:c}").Width(75).Title("Cost").Filterable(false);
columns.Bound(p => p.Manifest).Title("Mani").Width(55);
columns.Bound(p => p.VendPO).Title("Ven PO#").Width(120);
columns.Bound(p => p.VendRef).Title("Ven Ref#").Width(120);
columns.ForeignKey(p => p.CarrCode, (System.Collections.IEnumerable)ViewData["defaultCarrCode"], "CarrCode", "CarrDesc").EditorTemplateName("CarrDescAutoComplete").Title("Truck").Width(120);
columns.Bound(p => p.FrghtRate).Format("{0:c}").Width(75).Title("Frght").Filterable(false);
columns.Bound(p => p.Comment).Title("Comment").Width(120);
columns.Command(command =>
{
// command.Edit();
command.Destroy();
}).Width(110);
})
.DataSource(dataSource => dataSource
.SignalR()
.AutoSync(true)
.Events(events => events.Push(#<text>
function(e) {
// var notification = $("#notification").data("kendoNotification");
// notification.success(e.type);
}
</text>))
.PageSize(24)
.Transport(tr => tr
.Promise("hubStart")
.Hub("hub")
.Client(c => c
.Read("read")
.Create("create")
.Update("update")
.Destroy("destroy"))
.Server(s => s
.Read("read")
.Create("create")
.Update("update")
.Destroy("destroy"))
)
.Schema(schema => schema
.Model(model =>
{
model.Id(p => p.TempOrderID);
model.Field(p => p.CustCode).Editable(true);
model.Field(p => p.DueDate).Editable(true);
model.Field(p => p.LoadDate).Editable(true);
model.Field(p => p.ProdNum).Editable(true);
model.Field(p => p.Qty).Editable(true);
model.Field(p => p.CarrCode);
model.Field(p => p.VendCode).Editable(true);
model.Field(p => p.SalePrice).Editable(true);
}
))))
Here is the javascript:
<script>
function onDataBound(arg) {
alert("Grid data bound");
}
</script>
To summarize, I'm looking to color the rows conditionally. To do this I need to fire a DataBound event and go through the table and update the CSS. What do you guys think?
Okay, very silly mistake. I have multiple grids in this project that all share the same javascript file. I didn't realize I already had declared a 'onDataBound' function.
I renamed the grid event 'onDataBoundTempOrders' and wrote the appropriate javascript.
Here is ultimately the solution:
.Events(events => events.DataBound("onDataBoundTempOrders"))
Javascript:
function onDataBoundTempOrders(e) {
var grid = this;
grid.tbody.find('>tr').each(function () {
var dataItem = grid.dataItem(this);
$(this).css("background-color", dataItem.EventHexCode);
});
$("#grid tr.k-alt").removeClass("k-alt");
}
So now when a user selects a hex color, it's stored in the table. The hex code is applied via jquery to the table row. Works like a champ.

Reordering of Kendo UI Grid columns based on the order of a list of elements

Good day,
I have a list which is having elements, based on that list the grid will be obtained. I've a requirement of changing the order of elements in that list. So when i change the order of list and run the report, the grid is obtaining with the order of before list but not with the newly changed order.
Here is the list:
#Html.ListBox("multiselect_to", Model.AvailableColumnsList, new { #class = "form-control bdr_rad_3", size = "8", multiple = "multiple" })
Here is the Kendo Grid code:
#(Html.Kendo().Grid<Entrada.CustomerPortal.UI.Models.JobReport>()
.Name("JobReportGrid")
.ToolBar(tools => tools.Pdf())
.Pdf(pdf => pdf
.AllPages()
.FileName("Kendo UI Grid Export.pdf")
.ProxyURL(Url.Action("Excel_Export_Save", "JobReports")))
.ToolBar(tools => tools.Excel())
.Excel(excel => excel
.AllPages(true)
.FileName("Kendo UI Grid Export.xlsx")
.ProxyURL(Url.Action("Excel_Export_Save", "JobReports")))
.ColumnMenu()
.Columns(columns =>
{
columns.Bound(p => p.JobNumber)//.Title("Job <br/> Number")
.Width(colWidth["Job Number"])
.ClientTemplate("<a class='jobReportGridJN' jnum='#=JobNumber#'>" + "#=JobNumber#" + "</a>"+
#" #if(STAT== true) {# <span><img src='" + Url.Content("~/Images/stat-icon.png") + "'> </span>#}#");
columns.Bound(p => p.DictatorID);
columns.Bound(p => p.JobType);//.Title("Job <br/> Type");
columns.Bound(p => p.DeviceGenerated)//.Title("Device <br/> Generated")
.Width(colWidth["Device Generated"]);
columns.Bound(p => p.AppointmentDate)//.Title("Appointment <br/> Date")
.Width(colWidth["Appointment Date"])
.Format(colFormat["Appointment Date"]);
columns.Bound(p => p.InProcess)//.Title("In <br/> Process")
.Width(colWidth["In Process"])
.Format(colFormat["In Process"]);
columns.Bound(p => p.EditingComplete)
.Width(colWidth["Editing Complete"])
.Format(colFormat["Editing Complete"]);
columns.Bound(p => p.JobStatus);//.Title("Job <br/> Status");
columns.Bound(p => p.MRN);
columns.Bound(p => p.Patient);
})
.Groupable()
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single)
.Type(GridSelectionType.Row))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read
.Action("JobSearchPaginationGrid", "JobReports")
.Data("residentsReadData"))
.Events(events => events.Error("error_handler"))
.PageSize((int)ViewData["PageSize"])
.Group(group => group.Add<string>((string)TempData["GridGroupBy"]))
.ServerOperation(true)
)
.Pageable(pager => pager.Messages(Info => Info.Empty("No Results Found")))
.Sortable()
.Resizable(resize => resize.Columns(true))
.Scrollable().Selectable(s => s.Mode(GridSelectionMode.Single).Type(GridSelectionType.Row))
)
Image for Kendo UI grid columns before changing the order of list of elements
Image for List after changing the order
So, Can i reorder the Grid columns based on that list elements after changing the order of list?
It would be more helpful, if anyone answer quickly.
Thanks,
Sai
Haven't tried this myself but after a minute of googling there seems to be 2 steps involved in the process of achieving this if I understand it correctly:
First you have to set reorderable to true for the grid
.Reorderable(reorder => reorder.Columns(true))
http://demos.telerik.com/aspnet-mvc/grid/column-reordering
Reordering the columns programatically at list change event:
var grid = $("#JobReportGrid").data("kendoGrid");
grid.reorderColumn(newOrderIndex, grid.columns[currentIndex]);
http://docs.telerik.com/KENDO-UI/api/javascript/ui/grid#methods-reorderColumn

How to display GUID in Kendo Grid?

I just want to display a GUID from my model in a Kendo grid in the view, but I am getting this error each time:
The model item passed into the dictionary is of type 'System.Guid',
but this dictionary requires a model item of type 'System.String'.
This is my grid code:
#(Html.Kendo().Grid(Model.revisions)
.Name("RevisionsGrid")
.Columns(columns =>
{
columns.Bound(p => p.RevisionInfo.Id).Title("Revision ID");
columns.Bound(p => p.Accident.Id).Title("Accident ID")
.ClientTemplate("#= (Accident.Id == null) ? '' : Accident.Id.toString() #");
columns.Bound(p => p.RevisionInfo.RevisionDate).Title("Date Modified");
columns.Bound(p => p.RevisionInfo.User.Name).Title("By User");
columns.Command(command => command.Custom("ViewPdf").Text("View PDF").Click("getPdf"));
})
.Selectable()
.Pageable(p => p.PageSizes(new[] { 5, 10, 25 }))
.DataSource(dataSource => dataSource
.Server()
.Model(model =>
{
model.Id(p => p.RevisionInfo.Id);
model.Field(p => p.Accident.Id).DefaultValue(Guid.NewGuid());
}))
The problem is with the second column which is bound to Accident.Id, a GUID type. My attempts at fixing this included adding the ClientTemplate to that column & adding a default value for it, but neither of these helped. I also tried just adding ToString() in the column definition but then I get a different error about .Bound() only taking a property access method as an argument.
Is there some place to convert the GUID to a string in order to display it here?
I figured it out. In order to have the Kendo grid accept something that's not a string you need to specify a template for the column, in which you can call ToString(). I couldn't call it in binding.
columns.Bound(p => p.Accident.Id).Title("Accident ID")
.Template(p => p.Accident.Id.ToString());

Kendo UI grid won't populate from ajax dataSource MVC

I'm trying to populate kendo grid with my model from ajax call. This is my Kendo Ui Grid with Html.Helpers in .cshtml
<div id="grid">
#(Html.Kendo().Grid<OtpadModel.AddressObject>()
.Name("Grid")
.Pageable()
.Sortable()
.Selectable(sel =>
{
sel.Mode(GridSelectionMode.Single);
})
.Filterable()
.Scrollable()
.Events(events => events.Change("onChange"))
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetAddressObjects", "AddressObject"))
.Model(model => model.Id(p => p.ID)))
.Columns(columns => {
columns.Bound(p => p.KeyNumber).Title("Šifra objekta");
columns.Bound(p => p.ObjectType.Type).Title("Vrsta objekta");
columns.Bound(p => p.ObjectOwners.FirstOrDefault().Owner.Name).Title("Ime vlasnika");
columns.Bound(p => p.ObjectOwners.FirstOrDefault().Owner.Surname).Title("Prezime vlasnika");
columns.Bound(p => p.Address.Street).Title("Ulica");
columns.Bound(p => p.Address.Number).Title("Broj");
columns.Bound(p => p.Address.City.Name).Title("Grad");
columns.Bound(p => p.ResidentalArea).Title("Površina");
columns.Bound(p => p.ResidentsNumber).Title("Članovi");
columns.Bound(p => p.TuristBedsNumber).Title("Turistički kreveti");
})
)
</div>
My controller method implementation is:
public ActionResult GetAddressObjects([DataSourceRequest] DataSourceRequest request)
{
IEnumerable<AddressObject> addressObjects = unitOfWork.AddressObjectRepository.Get(includeProperties: "ObjectType, Address, ObjectOwners");
DataSourceResult result = addressObjects.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
}
I have all refernces. I can populate from my server side, so when I write Grid(Model) grid is populated but I don't want this.
Thank you all for your huge help. The problem was that one of my classes had one virtual property and the problem is that virtual keyword. You cannot have anything virtual, map always to ViewModel. But accidentally, one of my properties in my ViewModel was virtual (copy, paste mistake).
Set the property autobind to false.
#(Html.Kendo().Grid<OtpadModel.AddressObject>()
.Name("Grid")
.Pageable()
.Sortable()
.Selectable(sel =>
{
sel.Mode(GridSelectionMode.Single);
})
.AutoBind(false)
.Filterable()
.Scrollable()
.Events(events => events.Change("onChange"))
.Groupable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetAddressObjects", "AddressObject"))
.Model(model => model.Id(p => p.ID)))
.Columns(columns => {
columns.Bound(p => p.KeyNumber).Title("Šifra objekta");
columns.Bound(p => p.ObjectType.Type).Title("Vrsta objekta");
columns.Bound(p => p.ObjectOwners.FirstOrDefault().Owner.Name).Title("Ime vlasnika");
columns.Bound(p => p.ObjectOwners.FirstOrDefault().Owner.Surname).Title("Prezime vlasnika");
columns.Bound(p => p.Address.Street).Title("Ulica");
columns.Bound(p => p.Address.Number).Title("Broj");
columns.Bound(p => p.Address.City.Name).Title("Grad");
columns.Bound(p => p.ResidentalArea).Title("Površina");
columns.Bound(p => p.ResidentsNumber).Title("Članovi");
columns.Bound(p => p.TuristBedsNumber).Title("Turistički kreveti");
})
Then, in your document ready or some other page event, execute this code:
var grid = $("#yourgridElementName").data("kendoGrid");
grid.dataSource.read();
Hope this helps. Good luck.

Kendo UI difficulty getting Errors from grid model

In a Kendo UI grid I have an InLine edit which I am validating server side and if errors exist I return them in the json. I have gotten this far, but I am struggling to pull those errors out of the object to handle them. I will put in the code below starting with the problem and working backward.
I am grabbing the model from the Edit event. The model is populated, I can see the errors in the console, but the value of my errors variable in the below is null.
function onEdit(e) {
var errors = e.model.Errors;
console.log(errors);
console.log(e.model);
};
Here is my cshtml grid setup where I configure the Edit event and editable code.
#(Html.Kendo().Grid<RosterGridViewModel>()
.Name(gridId)
.HtmlAttributes(new {style="height: 400px;"})
.Columns(columns => {
columns.Bound(p => p.ApprovalStatus);
columns.Bound(p => p.LastName);
columns.Bound(p => p.FirstName);
columns.Bound(p => p.Birthdate).Format("{0:M/dd/yyyy}");
columns.Bound(p => p.Uic).Title("UIC");
columns.Bound(p => p.DateAdded).Format("{0:M/dd/yyyy}");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(190);
})
.Sortable()
.Scrollable()
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple))
.Events(events => events.DataBound("onDataBound").Edit("onEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Read(o => o.Action(AppRoute.RosterGridRead.ToMethod(), AppRoute.RosterGridRead.ToController()))
.Update(o => o.Action(AppRoute.RosterEdit.ToMethod(), AppRoute.RosterEdit.ToController()))
.Destroy(o => o.Action(AppRoute.RosterGridDestroy.ToMethod(), AppRoute.RosterGridDestroy.ToController()))
.Group(groups => groups.Add(p => p.School))
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Id).Editable(false);
model.Field(p => p.ApprovalStatus).Editable(false);
model.Field(p => p.DateAdded).Editable(false);
}
)
)
.ToolBar(toolbar => toolbar.Custom().Text(ActionLabel.DeleteSelection.GetDescription()).HtmlAttributes(new { onclick = "deleteSelection(event)" }))
)
You have to convert the e.model.Errors object to JSON first as shown below and then you can grab any property/key you need.
e.model.Errors.toJSON().Message

Categories

Resources