Frequently Asked Questions
This article lists some of the most frequently asked questions when working with the Telerik UI Grid component for ASP.NET MVC.
How can I display HTML in Grid columns?
By default, the Telerik UI Grid for ASP.NET MVC encodes the HTML entities that are included in its data. To prevent this, call the Encoded
method and pass false
as its argument.
columns.Bound(o => o.Description).Encoded(false);
How can I customize the way properties are displayed in Grid-bound columns?
-
If the Grid is configured for server binding, use the
Template
method to customize the default column template.The
Template
method needs a templated Razor delegate when used in Razor views. The bound item is available through the@item
parameter.@model IEnumerable<Product> @(Html.Kendo().Grid(Model) .Name("Grid") .Columns(columns => { columns.Bound(p => p.Title).Template(@<text> <strong>@item.Title</strong> </text>); }) )
Here is another example that shows how to set the server-side detail template of the Grid through the DetailTemplate() option:
@model IEnumerable<Product>
@(Html.Kendo().Grid(Model)
.Name("Grid")
.DetailTemplate(@<text>
<div>ProductID: @item.ProductID</div>
<div>ProductName: @item.ProductName</div>
<div>UnitsInStock: @item.UnitsInStock</div>
<div>UnitPrice: @item.UnitPrice</div>
<div>UnitsOnOrder: @item.UnitsOnOrder</div>
<div>Discontinued: @item.Discontinued</div>
</text>)
...
)
It is important to note that you can use only-server templates when the Grid is server-bound
. They are not available in Ajax or WebService binding mode. For these cases, you will need to use Client Templates.
- If the Grid is
Ajax-bound
, use theClientTemplate
method. The value should be a string, which represents a valid Kendo UI Template.
.Columns(columns =>
{
columns.Bound(p => p.Title).ClientTemplate("<strong>#: Title #</strong>");
})
How can I apply conditional logic to client column templates?
A Kendo UI Template may contain arbitrary JavaScript code. The #
symbol is used to denote JavaScript blocks.
The following example demonstrates the conditions in the ClientTemplate
.
columns.Bound(p => p.ProductName).ClientTemplate(
"# if (HasIcon == true) { #" +
"<img src='" + Url.Content("~/Content/icons/") + "#= ProductID #.png' alt='#= ProductName # icon' />" +
"# } else { #" +
"#: ProductName #" +
"# } #"
);
How can I apply conditional logic to column templates for server-bound Grids?
The following example demonstrates the syntax when you use a column template in a server-bound Grid.
columns.Bound(p => p.ProductName).Template( @<text>
@if(@item.ProductName != null){
@item.ProductName
} else {
"No data"
}
</text>
);
How can I display checkboxes in Ajax-bound Grids?
The checked
attribute specifies whether a checkbox is displayed as checked or not checked. Use a condition to set that attribute.
The following example demonstrates how to display a checkbox in a bound ColumnClientTemplate
.
columns.Bound(p => p.Enabled).ClientTemplate(
"<input type='checkbox' value='#= ProductID #' " +
"# if (Enabled) { #" +
"checked='checked'" +
"# } #" +
"/>"
);
How can I use action links?
-
For server-bound Grids, use the
Template
method. The following example demonstrates an action link in a Grid column.columns.Bound(p => p.ProductID).Template(@<text> @Html.ActionLink("Show Product Details", "ProductDetails", new { id = @item.ProductID } )> </text>);
-
For Ajax-bound Grids, use the
ClientTemplate
method. The following example demonstrates an action link in an Ajax-bound Grid column.columns.Bound(p => p.ProductID).ClientTemplate( "<a href='" + Url.Action("ProductDetails", "Product") + "/#= ProductID #'" + ">Show Product Details</a>" );
How can I use JavaScript functions in client column templates?
The Kendo UI Template has an implicit parameter called data
. Use it as the argument of the JavaScript function.
The following example demonstrates how to use a JavaScript function in the ClientTemplate
.
// Omitted for brevity.
columns.Bound(p => p.ProductID).ClientTemplate("#= productDetails(data) #");
// Omitted for brevity.
<script>
function productDetails(product) {
var action = '@Url.Action("ProductDetails", "Product")';
var html = kendo.format("<a href='{0}/{1}'>Show Product Details</a>",
action,
product.ProductID
);
return html;
}
</script>
How can I use Kendo UI widgets inside Grid client column templates?
The script
tags are not automatically evaluated inside a Grid client column template, so the included widgets are not initialized. The scripts must be evaluated manually in the Grid's dataBound
event.
The following example demonstrates how to add a Kendo UI Menu inside a Grid column template. Note that the Menu requires the Grid cells to allow overflowing, which is disabled by default.
@(Html.Kendo().Grid<ModelType>()
.Name("GridID")
.Columns(columns => {
columns.Template(@<text></text>).HtmlAttributes(new { @class = "templateCell" }).ClientTemplate(
Html.Kendo().Menu()
.Name("menu_#=OrderID#")
.Items(its =>
{
its.Add().Text("foo").Items(nested =>
{
nested.Add().Text("bar");
nested.Add().Text("baz");
});
})
.ToClientTemplate().ToHtmlString()
);
})
.Events(ev => ev.DataBound("initMenus"))
)
function initMenus(e) {
$(".templateCell").each(function(){
eval($(this).children("script").last().html());
});
}
.k-widget .templateCell
{
overflow: visible;
}
How can I change the format of bound columns?
Use the Format
method. the value should be a valid number
or date
format.
The following example demonstrates how to specify the format of a bound column.
columns.Bound(o => o.OrderDate).Format("{0:d}"); // Will use the short date pattern
How can I add Kendo UI icons to custom command buttons?
A list of the available Kendo UI icons and their CSS classes is available in the demo on styling and icons.
The following example demonstrates how to add Kendo UI icons to custom command buttons.
@(Html.Kendo().Grid()
.Name("grid")
.Columns(columns =>
{
columns.Command(command => { command.Custom("myCommand").Click("myCommandClick").Text("My Text").IconClass("k-icon k-i-custom"); });
})
)
<script>
function myCommandClick() {
console.log("custom command click event handler");
}
</script>
How can I send values to my action method when binding the Grid?
If the Grid is server-bound, use the overload
method which accepts route values.
The following example demonstrates how to send data in a server-bound Grid.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Server()
.Read(read => read.Action("Read", "Home", new { userID = (int)ViewData["UserID"] }))
)
// Omitted for brevity.
If the Grid is Ajax-bound, use the Data
method to specify the name of the JavaScript function, which will return the additional data.
The following example demonstrates how to send additional data in an Ajax-bound Grid.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.Read(read => read
.Action("Read", "Home")
.Data("additionalData")
)
)
// Omitted for brevity.
<script>
function additionalData() {
return {
userID: 42,
search: $("#search").val()
};
}
</script>
The property names of the object that are passed as additional data must not match the property names in the
ViewModel
. Otherwise, the MVC binder will not recognize which property corresponds to theViewModel
and which to the additionaldata
object.
How can I reload data in Ajax-bound Grids?
Use the read
method of the DataSource.
The following example demonstrates how to reload an Ajax-bound Grid.
var grid = $("#Grid").data("kendoGrid");
grid.dataSource.read();
How can I convert my models to view model objects?
The ToDataSourceResult
extension method supports an optional selector, which can be used to convert the processed data to some other type.
To flatten your data, use View Model objects, reduce the number of serialized properties, or avoid circular reference serializaton exceptions.
The following example demonstrates how to convert the processed data.
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
var northwind = new NorthwindDataContext();
var orders = northwind.Orders;
var result = orders.ToDataSourceResult(request, o => new {
OrderID = o.OrderID,
CustomerName = o.Customer.ContactName
});
return Json(result);
}
How can I avoid circular reference exceptions?
The JavaScriptSerializer
class throws an exception if the serialized object contains circular references. To avoid this, use a View Model and exclude the
properties which create the circular references.
The following example demonstrates how to avoid circular references.
// Models.
public class Order
{
public int OrderID { get; set; }
// This property creates a circular reference because of the Customer class.
// Refers to the Order class through the Orders property.
public Customer Customer { get; set; }
}
public class Customer
{
public string ContactName { get; set; }
public IEnumerable<Order> Orders { get; set; }
}
// Action.
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
var northwind = new NorthwindDataContext();
var orders = northwind.Orders;
// Avoid the circular reference by creating a View Model object and skipping the Customer property.
var result = orders.ToDataSourceResult(request, o => new {
OrderID = o.OrderID,
CustomerName = o.Customer.ContactName
});
}
How can I handle errors in Ajax binding mode?
Use the error
event of the DataSource. Apply the Error
method from the fluent API to specify the name of the JavaScript function which will handle the event.
The following example demonstrates how to handle errors in the Ajax binding mode.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.Events(events => events.Error("onError"))
// Omitted for brevity.
<script>
function onError(e, status) {
alert("A server error has occurred!");
}
</script>
How can I see what the server response is?
The Kendo UI Grid makes HTTP
requests. Use the developer tools of your browser to inspect the communication between the browser and the web server. In case of a server-side exception, the HTTP
status code is 500
and the server response contains the detailed exception stack-trace.
How can I implement paging, sorting, filtering, and grouping?
If your model supports the IQueryable
interface or is DataTable
, the Grid does paging, sorting, filtering, grouping, and aggregates—DataTable
binding supports only the count
aggregate—automatically.
For server-binding scenarios, no additional steps are required. Just pass the IQueryable
to the Grid
constructor. For additional information on the Grid server binding, refer to this article.
For Ajax-binding scenarios, the ToDataSourceResult
extension method must be used to perform the data processing. For additional information on the Grid Ajax binding, refer to this article.
If your model does not implement IQueryable
, implement custom binding. This means that you are responsible for the paging, sorting, filtering, and grouping of the data. For more information on the Grid custom binding, refer to this article.
All data operations are performed at database server level if the underlying
IQueryable
provider supports translation of expression trees to SQL. Kendo UI Grid for ASP.NET MVC has been tested with the following frameworks:
- Entity Framework
- Linq to SQL
- Telerik OpenAccess
- NHibernate
How can I configure Grids to perform paging, sorting, filtering, and grouping in memory?
By default, paging, sorting, filtering and grouping initiate the making of Ajax requests. The ToDataSourceResult
extension method processes the data source server-side. To prevent this, call the ServerOperation
method and pass false
as the argument.
The following example demonstrates how to perform paging, sorting, filtering, and grouping in memory.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.ServerOperation(false)
// Omitted for brevity.
How can I prevent Ajax response caching?
Prevent the caching and browser re-use of Ajax responses in either of the following ways:
-
Use an
OutputCache
attribute for the action method.[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] public JsonResult MyReadMethod() { /* ... */ }
Configure the Kendo UI DataSource to make
POST
instead ofGET
Ajax requests for theRead
action.-
Use jQuery's
ajaxSetup
configuration method. This influences all Ajax requests that the web application performs.$.ajaxSetup ({ cache: false });
How can I display model state errors?
The ToDataSourceResult
extension method has an overload which accepts the ModelState
as parameter. That overload serializes any model state errors in the JSON response and the error
event of the DataSource is raised.
The following example demonstrates how to display model state errors.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.Events(events => events.Error("onError"))
// Omitted for brevity.
<script>
function onError(e, status) {
if (e.errors) {
var message = "The following errors have occurred:\n";
$.each(e.errors, function(key, value) {
if (value.errors) {
message += value.errors.join("\n");
}
});
alert(message);
}
}
</script>
How can I create custom pop-up editors?
The Kendo UI Grid for ASP.NET MVC uses the Html.EditorForModel
to create the editing form. This method relies on ASP.NET MVC editor templates. To create a custom editor template, create a partial view under the ~/Views/Shared/EditorTemplates
folder and specify it through the UIHint
attribute.
The Custom Object Templates blog post contains a lot of information about creating a custom editor template.
The Custom Popup Editor code library project contains a ready-to-run project.
The
Html.EditorForModel
is used only in popup edit mode. In-cell and in-line edit modes useHtml.EditorFor
and pass the expression used to declare the bound column—for example,Html.EditorFor(o => o.OrderDate)
.
How can I specify default property values when new items are created?
The Kendo UI Grid uses the default .NET
property values when creating a new object—""
for strings, 0
for numeric types, null
for reference types. To change this behavior, use the Model
method of the DataSource.
The following example demonstrates how to specify default property values.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.Model(model =>
{
model.Field(p => p.Name).DefaultValue("N/A");
model.Field(p => p.Price).DefaultValue(9.99);
})
// Omitted for brevity.
How can I create helper methods rendering predefined widgets I can further configure?
In many cases Kendo UI wants to avoid setting similar settings to all the places where a widget is used. Instead of defining the same settings all over again, create a helper method that wraps a Kendo UI widget which is already configured.
First, create such an extension method in a static class.
The following example demonstrates how to create a custom helper that wraps the Grid configurator.
public static class Extensions
{
public static GridBuilder<T> MyGrid<T>(this HtmlHelper helper)
where T: class
{
return helper.Kendo().Grid<T>()
.Scrollable();
}
}
@using TheNamespaceOfTheExtensionsClass
@(Html.MyGrid.Name("foo")) // The Grid is already configured to be Scrollable
If you want to avoid adding the
using
statement in each view that uses this component, add a namespace reference to theWeb.config
file inside theViews
folder of your project.
How can I mark certain properties as read-only?
By default, all properties are read-only. Decorate the read-only properties with the ReadOnly
data annotation attribute or use the Editable
configuration method.
The following example demonstrates the Read-only property through the ReadOnly
attribute.
public class Order
{
[ReadOnly(true)]
public int OrderID { get; set; }
}
The following example demonstrates the Read-only property through the Editable
method.
// Omitted for brevity.
.DataSource(dataSource => dataSource.Ajax()
.Model(model =>
{
model.Field(o => o.OrderID).Editable(false);
})
// Omitted for brevity.
The
ReadOnly
andEditable
settings work only in in-line and in-cell editing modes. Use a custom popup editor if you want to exclude certain properties from the editor form.
How can I use Kendo UI widgets as editors for dates and numbers?
Use custom editor templates. ASP.NET MVC looks for a partial view, named after the type—for example, DateTime.cshtml
. Telerik UI for ASP.NET MVC ships with a few ready-to-use editor templates. They are located in the \wrappers\aspnetmvc\EditorTemplates
folder. The editor templates are available in two flavors—the ascx
folder contains the WebForms
view engine version, whereas the razor
folder contains the Razor
view engine version. To use these editor templates in your application, copy all files from the corresponding folder (ascx
or razor
) to ~/Views/Shared/EditorTemplates
(you may need to create this folder if it does not exist yet).
To validate a date by using the Kendo UI DateTimePicker:
- Add a new partial view to the
~/Views/Shared/EditorTemplates
folder—for example,KendoDateEditor.ascx
orKendoDateEditor.cshtml
(if you are using the Razor view engine). -
Add a Kendo UI DropDownList to that partial view.
@(Html.Kendo().DateTimePicker() .Value(DateTime.Now) .DateInput() )
-
Decorate the
Date
property in the model by using theUIHint
attribute.public class Order { public int OrderID { get; set; } public string ShipCountry { get; set; } [UIHint("KendoDateEditor")] public Date OrderDate { get; set; } }
To validate a number by using the Kendo UI NumericTextBox:
- Add a new partial view to the
~/Views/Shared/EditorTemplates
folder—for example,KendoNumberEditor.ascx
orKendoNumberEditor.cshtml
(if you are using the Razor view engine). -
Add a Kendo UI DropDownList to that partial view.
@(Html.Kendo().NumericTextBox() .Round(false) .Spinners(false) )
-
Decorate the
number
property in the model by using theUIHint
attribute.public class Order { public int OrderID { get; set; } public string ShipCountry { get; set; } [UIHint("KendoNumberEditor")] public decimal Price { get; set; } }
How can I distinguish between Add and Edit mode?
To distinguish between the insert and update modes, you can use the isNew
method in combination with the edit event handler of the grid:
Grid Edit Event
Here is a basic sample for reference:
// Omitted for brevity.
.Events(events => events.Edit("onEdit"))
function onEdit(args) {
if (args.model.isNew() == false) {
// textbox
$("#ShipName").attr("readonly", true);
// dropdownlist
var kendoDdl = $("#ShipCountry").data("kendoDropDownList");
kendoDdl.readonly(true);
}
}