Maddening... Trying to utilize AJAX reads with a Kendo Grid. I've done quite a few binding to data passed down from the model. I copy the code straight from the KendoUI site and tweak to meet my demands:
#(Html.Kendo().Grid<FaultReport2.Models.usp_CMC_TopIssues_Result>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.description).Title("Description");
columns.Bound(p => p.responsible).Title("Responsibility");
columns.Bound(p => p.charged_time).Title("Time");
columns.Bound(p => p.responsible).Title("Responsible");
columns.Bound(p => p.root_cause).Title("Root Cause");
columns.Bound(p => p.counter_measure).Title("Countermeasure");
columns.Bound(p => p.status).Title("Status");
})
.Pageable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read
.Action("cmcTopIssues", "FaultInfo", new { equipment_id = Model.area_id, start_date = Model.start_date })
)
)
)
Controller code for the read.Action():
public ActionResult cmcTopIssues(int equipment_id, DateTime start_date)
{
var db = new Models.FAULTEntities1();
var top_issues = db.usp_CMC_TopIssues(equipment_id, start_date).ToList();
return Json(top_issues, JsonRequestBehavior.AllowGet);
}
Does not work. I verify that my cmcTopIssues method is being called and that the top_issues var is being filled. It just does not populate the grid.
When I switch over to local and pass the data down through the model, it works fine.
Any help would be appreciated.
Hmm, perhaps try modifying your action method as shown in here so that you return a Kendo data source result instead:
public ActionResult cmcTopIssues([DataSourceRequest]DataSourceRequest request, int equipment_id, DateTime start_date)
{
var db = new Models.FAULTEntities1();
var top_issues = db.usp_CMC_TopIssues(equipment_id, start_date).AsEnumerable();
return Json(top_issues.ToDataSourceResult(request));
}
Related
When I set the datasource to WebAPI binding, the HTTP GET is being invoked on the controller and it returns the correct data. The problem is that my Kendo Grid is not binding the data correctly, instead I get an empty grid as a result.
#(Html.Kendo().Grid(Model)
.Name("Accounts")
.Columns(columns =>
{
columns.Bound(c => c.Description).Title("Account Name");
columns.ForeignKey(c => c.Type, (System.Collections.IEnumerable)ViewData["accountTypes"], "Id", "Name").Title("Account Type");
columns.ForeignKey(c => c.Currency, (System.Collections.IEnumerable)ViewData["currencyTypes"], "Id", "Name").Title("Account Currency");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(210);
})
.Sortable(sortable =>
{
sortable.SortMode(GridSortMode.SingleColumn);
sortable.AllowUnsort(false);
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5)
)
.ToolBar(toolbar => { toolbar.Create(); })
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.WebApi()
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Currency).DefaultValue(0).Editable(true);
model.Field(p => p.Description).Editable(true);
model.Field(p => p.Type).Editable(true);
})
.ServerOperation(true)
.Read(read => read.Action("Get", "Accounts"))
.Create(create => create.Action("Post", "Accounts"))
.Update(update => update.Action("Put", "Accounts", new { id = "{0}" }))
.Destroy(destroy => destroy.Action("Delete", "Accounts", new { id = "{0}" }))
.PageSize(10)
)
)
Controller
// GET: api/values
[HttpGet]
public DataSourceResult Get([DataSourceRequest]DataSourceRequest request)
{
return _context.Accounts.ToDataSourceResult(request);
}
I always get an HTTP 200 OK as a result of the paging or sorting command, but the grid is empty afterwards. The URL generated by Kendo is:
http://localhost:58829/Accounts/Get?sort=&page=1&pageSize=10&group=&filter=
Which actually returns JSON when I open it with a browser.
The problem seems to be that you are mixing two different ways to load the data. On the one hand you are passing the Model by param to the grid (this approach is used when ServerOperation = false) and on the other hand you are setting ServerOperation = true and specifying a read action.
The reason why the grid is empty in this case is probably because either the Model is empty.
Take a look at this demo example for a reference on how to implement the remote source databinding: http://demos.telerik.com/aspnet-core/grid/remote-data-binding
Example View:
Example controller:
Hope this helps KendoGrid is an awesome library but like many other libraries it could definitely use better exception handling and more user friendly exceptions :) In my opinion the grid should have shown an exception in this case.
The problem was this: when declaring the Kendo Grid and passing the Model as a parameter like so:
#(Html.Kendo().Grid(Model)
You need to remove the .Read() action, and make sure to use .ServerOperation(false). This works either with WebApi binding or Ajax binding:
.DataSource(dataSource => dataSource
.WebApi() // also works with .Ajax()
.Model(model =>
{
model.Id(p => p.Id);
}
)
.ServerOperation(false)
.Create(create => create.Action("Post", "Invoices"))
.Update(update => update.Action("Put", "Invoices", new { id = "{0}" }))
.Destroy(destroy => destroy.Action("Delete", "Invoices", new { id = "{0}" }))
.PageSize(10)
)
Also, the DataSourceResult Get() method can be removed.
Binding kendo grid to local data, It ajax current page("http://localhost"), how to solve?
When the page load, the current page("http://localhost") get 2 times.
My View
#(Html.Kendo().Grid<Models.RecordModel>()
.Name("ResultGrid")
.Columns(columns =>
{
columns.Bound(p => p.ProductTitle).Width(250).Title("Title").HtmlAttributes(new {#class = "GridTextLeft"});
columns.Bound(p => p.ProductCode).Width(110).Title("Code").HtmlAttributes(new {#class = "GridTextLeft"});
})
.Scrollable(scr => scr.Height(380))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.PageSize(10)
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.ProductTitle);
model.Field(p => p.ProductCode);
})
)
.Resizable(resize => resize.Columns(true))
.Pageable(pager => pager
.ButtonCount(1)
.PreviousNext(true)
.Messages(t => t.Display("{2} item"))
)
)
It needs that Kendo Grid to be pointed to your controller method that returns data if it is Ajax binding:
...
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Products_Read", "Home")) //Set the action method which will return the data in JSON format.
)
)
...
Check the manual at http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/binding/ajax-binding .
UPDATE. If you require server binding then apply the BindTo method as per http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/binding/server-binding
I have a sample like this popup editing mode
I want to store my model while first inserting, and set default values.
#(Html.Kendo().Grid<License>()
.Name("popupGrid")
.Columns(columns =>
{
columns.Bound(p => p.LicenseId).Width(20).Hidden().HeaderHtmlAttributes(new { #title = "License" });
columns.ForeignKey(p => p.CustomerId, (System.Collections.IEnumerable)ViewData["customers"], "CustomerID", "CustomerName")
.Title("Customer").Width(200);
columns.Bound(p => p.VendorId).Width(20).HeaderHtmlAttributes(new { #title = "Vendor" });
columns.Bound(p => p.ProductId).Width(20).HeaderHtmlAttributes(new { #title = "Product" });
columns.Command(p => p.Edit().Text("Edit").HtmlAttributes(new { #title = "Edit" })).Width(80);
})
.ToolBar(toolbar => toolbar.Create().HtmlAttributes(new {#id ="MyAddButton" ,#title = "Add" }))
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("PopupEditView"))
.Events(e => e.Edit("onGridEdit").Save("onGridSave"))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(p => p.LicenseId))
.Create(create => create.Action("Create", "Home").Type(HttpVerbs.Post))
.Read(read => read.Action("Read", "Home").Type(HttpVerbs.Post))
.Update(update => update.Action("Update", "Home").Type(HttpVerbs.Post))
)
)
<script>
var myModel;
function onGridSave(e) {
if (e.model.isNew()) {
myModel = e.model;
}
}
function onGridEdit(e) {
if (e.model.isNew()&&myModel!=null) {
e.model.set("CustomerId", myModel.CustomerId);
e.model.set("VendorId", myModel.VendorId);
e.model.set("ProductId", myModel.ProductId);
}
}
</script>
But it's not working.
following code is not working too :
$(e.container).find('input[name="CustomerId"]').data("kendoDropDownList").value(myModel.CustomerId);//it's not giving error. but CustomerId is null in model of create method
Actually I want to this. But I don't know how to update datasource while prevent closing window.
You might try configuring your dropdownlist with valuePrimitive: true
http://docs.telerik.com/kendo-ui/api/javascript/ui/dropdownlist#configuration-valuePrimitive
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
I am using the following code. Can anybody tell me how will I use the page number instead of scroll bar?
My Index.cshtml page will be like
<div id="CustomerProfile">
<div id="GridCusotmerProfile">
#(Html.Kendo().Grid(Model)
.Name("grdCustomerProfile")
.Columns(coloumns =>
{
coloumns.Bound(p => p.CustomerID).Title("Customer ID");
coloumns.Bound(p => p.UserId).Title("User Id");
coloumns.Bound(p => p.ComapnyName).Title("Company Name");
coloumns.Bound(p => p.ContactPerson).Title("Contact Person");
coloumns.Bound(p => p.AccountNumber).Title("Account Number");
}
)
.Sortable()
.Scrollable(scrollable => scrollable.Virtual(true))
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read.Action("Virtualization_Read", "CustomerProfile"))
)
)
</div>
My Controller will be like the following
public List<CustomerProfileModel> CustomerDataSource(int page, int pagesize, int skip, int take)
{
List<CustomerProfileModel> ModelData = new List<CustomerProfileModel>();
take = skip + take + (page * 10);
var CustomerData = (from cp in context.CustomerProfile select cp).OrderBy(x => x.ComapnyName).Take(take).Skip(skip).ToList();
foreach (var items in CustomerData)
{
CustomerProfileModel Model = new CustomerProfileModel();
Model.CustomerID = items.CustomerID;
Model.AccountNumber = items.AccountNumber;
Model.ComapnyName = items.ComapnyName;
Model.ContactPerson = items.ContactPerson;
Model.UserId = items.UserId;
ModelData.Add(Model);
}
return ModelData;
}
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request, string page,string pagesize,string skip,string take)
{
return Json(CustomerDataSource(Convert.ToInt32(page),Convert.ToInt32(pagesize),Convert.ToInt32(skip),Convert.ToInt32(take)).ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
}
public List<CustomerProfileModel> CustomerDataSource(int page, int pagesize, int skip, int take)
{
List<CustomerProfileModel> ModelData = new List<CustomerProfileModel>();
take = skip + take + (page * 10);
var CustomerData = (from cp in context.CustomerProfile select cp).OrderBy(x => x.ComapnyName).Take(take).Skip(skip).ToList();
foreach (var items in CustomerData)
{
CustomerProfileModel Model = new CustomerProfileModel();
Model.CustomerID = items.CustomerID;
Model.AccountNumber = items.AccountNumber;
Model.ComapnyName = items.ComapnyName;
Model.ContactPerson = items.ContactPerson;
Model.UserId = items.UserId;
ModelData.Add(Model);
}
return ModelData;
}
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request, string page,string pagesize,string skip,string take)
{
return Json(CustomerDataSource(Convert.ToInt32(page),Convert.ToInt32(pagesize),Convert.ToInt32(skip),Convert.ToInt32(take)).ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
}
Please let me know if I need something else to get data as lazy loading.
Your on the right tracks, but it is actually a lot easier than you think. Your trying to hand roll functionality that Kendo handles with the `ToDataSourceResult() extension method.
The DataSourceRequest contains all the information needed for database operations, such as ordering, aggregates and paging. So you can simplfy your code down to pretty much the following (NOT TESTED)
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request)
{
var CustomerData = (from cp in context.CustomerProfile select cp); // don't call toList() this exectues the SQL and pulls data into memory, leave it as a Queryable object so we can pass it to kendo to add its expressions this will the be a Database operation
DataSourceResult result = CustomerData.ToDataSourceResult(request, x => new CustomerProfileModel(){
CustomerID = x.CustomerID;
AccountNumber = x.AccountNumber;
ComapnyName = x.ComapnyName;
ContactPerson = x.ContactPerson;
UserId = x.UserId;
});
return Json(result);
}
For further reading take a look at this link:
http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/ajax-binding
From the Kendo Site:
How do I implement paging, sorting, filtering and grouping?
If your model supports the IQueryable interface or is DataTable the grid will do paging, sorting, filtering, grouping and aggregates automatically. For server binding scenarios no additional steps are required - just pass the IQueryable to the Grid constructor. Check the server binding help topic for additional info.
For ajax binding scenarios the ToDataSourceResult extension method must be used to perform the data processing. Check the ajax binding help topic for additional information. If your model does not implement IQueryable custom binding should be implemented. This means that the developer is responsible for paging, sorting, filtering and grouping the data. More info can be found in the custom binding help topic.
Important:
All data operations will be performed at database server level if the underlying IQueryable provider supports translation of expression trees to SQL. Kendo Grid for ASP.NET MVC has been tested with the following frameworks:
Entity Framework
Linq to SQL
Telerik OpenAccess
NHibernate
.Columns(columns =>
{
columns.Bound(p => p.ID).Title("ID").Width(100).Visible(false);
columns.Bound(p => p.Apply).Title("Apply").Width(100);
columns.Bound(p => p.TaxName).Title("Tax Name").Width(100);
columns.Bound(p => p.TaxPercent).Title("Percent").Width(130);
columns.Bound(p => p.OrderApplied).Title("Oreder Applied").Width(130);
columns.Bound(p => p.Compund).Title("Compund").Width(130);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(172);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Sortable()
.Scrollable(scr=>scr.Height(430))
//.Scrollable(scrollable => scrollable.Virtual(true))
.HtmlAttributes(new { style = "height:430px;" })
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Events(events => events.Error("error_handler"))
.Model(model => model.Id(p => p.ID))
.ServerOperation(false)
.Create(update => update.Action("EditingInline_Create", "Taxes"))
.Read(read => read.Action("EditingInline_Read", "Taxes"))
.Update(update => update.Action("EditingInline_Update", "Taxes"))
.Destroy(update => update.Action("EditingInline_Destroy", "Taxes"))
)
)