Client Detail Templates
The Telerik UI Grid for ASP.NET Core enables you to show additional information for a data item by setting the detail template of the Grid.
For a runnable example, refer to the demo on detail templates in the Grid.
To configure the client detail template:
Defining the Client Details
To configure the Grid for ASP.NET Core to display additional details of the Product entity from the Northwind database:
-
Open
HomeController.cs
and add a new action method which will return the Products as JSON. The Grid makes Ajax requests to this action.public ActionResult Products_Read() { }
-
Add a new parameter of type
DataSourceRequest
to the action. This parameter will contain the current Grid request information—page, sort, group, and filter. Decorate that parameter with theDataSourceRequestAttribute
. This attribute will populate theDataSourceRequest
object from the posted data.public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request) { }
-
Use the
ToDataSourceResult
extension method to convert the Products to aDataSourceResult
object. That extension method will page, filter, sort, or group your data using the information provided by theDataSourceRequest
object.public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request) { using (var northwind = new NorthwindEntities()) { IQueryable<Product> products = northwind.Products; DataSourceResult result = products.ToDataSourceResult(request); } }
-
Return the
DataSourceResult
as JSON. Configure the Grid for Ajax binding.public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request) { using (var northwind = new NorthwindEntities()) { IQueryable<Product> products = northwind.Products; DataSourceResult result = products.ToDataSourceResult(request); return Json(result); } }
-
In the view, configure the Grid to use the action method created in the previous steps.
@(Html.Kendo().Grid<KendoGridClientDetailTemplate.Models.Product>() .Name("grid") .DataSource(dataSource => dataSource .Ajax() .Read(read => read.Action("Products_Read", "Home")) ) .Columns(columns => { columns.Bound(product => product.ProductID); columns.Bound(product => product.ProductName); }) .Pageable() )
<kendo-grid name="grid"> <datasource type="DataSourceTagHelperType.Ajax" page-size="20" <schema data="Data" total="Total"> <model id="ProductID"> <fields> <field name="ProductID" type="number" editable="false"></field> <field name="ProductName" type="string"></field> </fields> </model> </schema> <transport> <read url="@Url.Action("Products_Read" "Grid")" /> </transport> </datasource> <columns> <column field="ProductID" /> <column field="ProductName" /> </columns> <pageable enabled="true"/> </kendo-grid>
-
Define the client template using the Kendo UI for jQuery template syntax. The context of the template is the data item—Product entity— bound to the Grid.
Each
#
symbol that is not part of a template expression—#: #
,# #
or#= #
—must be escaped—\\#
.<script id="client-template" type="text/x-kendo-template"> <div>ProductID: #: ProductID #</div> <div>ProductName: #: ProductName #</div> <div>UnitsInStock: #: UnitsInStock #</div> <div>UnitPrice: #: UnitPrice #</div> <div>UnitsOnOrder: #: UnitsOnOrder #</div> <div>Discontinued: #: Discontinued #</div> </script>
-
Specify the
id
of the template by using theClientDetailTemplateId
method.@(Html.Kendo().Grid<KendoGridClientDetailTemplate.Models.Product>() .Name("grid") .DataSource(dataSource => dataSource .Ajax() .Read(read => read.Action("Products_Read", "Home")) ) .Columns(columns => { columns.Bound(product => product.ProductID); columns.Bound(product => product.ProductName); }) .Pageable() .ClientDetailTemplateId("client-template") )
<kendo-grid name="grid" detail-template-id="client-template"> <datasource type="DataSourceTagHelperType.Ajax" page-size="20" <schema data="Data" total="Total"> <model id="ProductID"> <fields> <field name="ProductID" type="number" editable="false"></field> <field name="ProductName" type="string"></field> </fields> </model> </schema> <transport> <read url="@Url.Action("Products_Read" "Grid")" /> </transport> </datasource> <columns> <column field="ProductID" /> <column field="ProductName" /> </columns> <pageable enabled="true"/> </kendo-grid>
Setting the Client Hierarchy
To configure the Grid for ASP.NET Core to display all Product entities that are available per the Category entity from the Northwind database:
-
Open
HomeController.cs
and add a new action method which will return the Category entities as JSON. The Grid makes Ajax requests to this action.public ActionResult Categories_Read() { }
-
Add a new parameter of type
DataSourceRequest
to the action. This parameter will contain the current grid request information - page, sort, group and filter. Decorate that parameter with theDataSourceRequestAttribute
. That attribute will populate theDataSourceRequest
object from the posted data.public ActionResult Categories_Read([DataSourceRequest]DataSourceRequest request) { }
-
Use the
ToDataSourceResult
extension method to convert the Categories to aDataSourceResult
object. That extension method will page, filter, sort, or group your data using the information provided by theDataSourceRequest
object.public ActionResult Categories_Read([DataSourceRequest]DataSourceRequest request) { using (var northwind = new NorthwindEntities()) { IQueryable<Category> categories = northwind.Categories; // Flatten the Category to avoid circular references during JSON serialization. DataSourceResult result = categories.ToDataSourceResult(request, category => new { category.CategoryID, category.CategoryName }); } }
-
Return the
DataSourceResult
as JSON. Now let's configure the Grid for AJAX binding.public ActionResult Categories_Read([DataSourceRequest]DataSourceRequest request) { using (var northwind = new NorthwindEntities()) { IQueryable<Category> categories = northwind.Categories; // Flatten the Category to avoid circular references during JSON serialization. DataSourceResult result = categories.ToDataSourceResult(request, category => new { category.CategoryID, category.CategoryName }); return Json(result); } }
-
Open
HomeController.cs
and add a new action method which will return the Product entities for a given category as JSON. The child Grid makes Ajax requests to this action.public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request, int categoryId) { using (var northwind = new NorthwindEntities()) { IQueryable<Product> products = northwind.Products.Where(product => product.CategoryID == categoryId); // Flatten the Product to avoid circular references during JSON serialization DataSourceResult result = products.ToDataSourceResult(request, product => new { product.ProductID, product.ProductName }); return Json(result); } }
-
In the view, configure the Grid for Ajax binding to
Categories_Read
.@(Html.Kendo().Grid<KendoGridClientHierarchy.Models.Category>() .Name("grid") .Columns(columns => { columns.Bound(category => category.CategoryID); columns.Bound(category => category.CategoryName); }) .DataSource(dataSource => dataSource.Ajax().Read(read => read.Action("Categories_Read", "Home")) ) )
<kendo-grid name="grid" > <datasource type="DataSourceTagHelperType.Ajax" page-size="20" <schema data="Data" total="Total"> <model id="CategoryID"> <fields> <field name="CategoryID" type="number" editable="false"></field> <field name="CategoryName" type="string"></field> </fields> </model> </schema> <transport> <read url="@Url.Action("Categories_Read" "Grid")" /> </transport> </datasource> <columns> <column field="CategoryID" /> <column field="CategoryName" /> </columns> <pageable enabled="true"/> </kendo-grid>
-
Define the client template using Kendo UI Template syntax. The context of the template is the Category entity bound to the Grid. The template itself contains another Grid bound to the
Products_Read
action.- Always call the
ToClientTemplate
method when using Telerik UI for ASP.NET Core helpers in a client template. - Escape the
#
characters used for a template expression when using a columnClientTemplate
in a detail template, so that the expression is evaluated in the correct context.
<script id="client-template" type="text/x-kendo-template"> @(Html.Kendo().Grid<KendoGridClientHierarchy.Models.Product>() .Name("grid_#=CategoryID#") // make sure the Name is unuque .Columns(columns => { columns.Bound(product => product.ProductID); columns.Bound(product => product.ProductName).ClientTemplate("<strong>\\#:ProductName\\#</strong>"); // escape the "#" characters }) .DataSource(dataSource => // Make a request to Products_Read and provide the current CategoryID as a route parameter. dataSource.Ajax().Read(read => read.Action("Products_Read", "Home", new { categoryId = "#=CategoryID#" })) ) .Pageable() .ToClientTemplate() ) </script>
@{ var url =@Url.Action("HierarchyBinding_Orders","Grid"); } <script id="client-template" type="text/html"> <kendo-grid name="grid_#=CategoryID#" is-in-client-template="true"> <columns> <column field="ProductID"> </column> <column field="ProductName" template="<strong>\\#:ProductName\\#</strong>""> // escape the "#" characters </column> </columns> <datasource type="DataSourceTagHelperType.Ajax"> <schema data="Data" total="Total" errors="Errors"> </schema> <transport> <read url="@Html.Raw(url+"?employeeID=#=EmployeeID#")" /> </transport> </datasource> <pageable enabled="true" /> </kendo-grid> </script>
- Always call the
-
Specify the
id
of the template using theClientDetailTemplateId
method.@(Html.Kendo().Grid<KendoGridClientHierarchy.Models.Category>() .Name("grid") .Columns(columns => { columns.Bound(category => category.CategoryID); columns.Bound(category => category.CategoryName); }) .DataSource(dataSource => dataSource.Ajax().Read(read => read.Action("Categories_Read", "Home")) ) .ClientDetailTemplateId("client-template") )
<kendo-grid name="grid" detail-template-id="client-template" > <datasource type="DataSourceTagHelperType.Ajax" page-size="20" <schema data="Data" total="Total"> <model id="CategoryID"> <fields> <field name="CategoryID" type="number" editable="false"></field> <field name="CategoryName" type="string"></field> </fields> </model> </schema> <transport> <read url="@Url.Action("Categories_Read" "Grid")" /> </transport> </datasource> <columns> <column field="CategoryID" /> <column field="CategoryName" /> </columns> <pageable enabled="true"/> </kendo-grid>
Handling Nested Client Templates
Nesting client templates are not an out-of-the-box feature the Kendo UI Core wrappers support. For more information on this issue, check the Grid troubleshooting section in invalid template errors when nesting client templates.