Telerik Extensions for ASP.NET MVC Manual |
Client Detail Template and Hierarchy |
Send Feedback |
Telerik Grid for ASP.NET MVC provides the ability to show additional info for a data item. This is done by defining the detail view for the grid and specifying its server and/or client template.
This help topic shows how to use the client detail view template which is used in ajax and web service binding scenarios.
Setting the client detail view template
Here is how to display additional details (properties) of the Employee object (from the Northwind database):

<%= Html.Telerik().Grid<MvcApplication.Models.Employee>() .Name("Employees") .DataBinding(dataBinding => dataBinding.Ajax() // Specify the action method which returns the Employee objects .Select("_Employees", "Home")) .Columns(columns => { columns.Bound(e => e.FirstName); columns.Bound(e => e.LastName); columns.Bound(e => e.Title); }) .DetailView(detailView => detailView.ClientTemplate( // Set the client template "<ul>" + "<li>Name: <#= FirstName #> <#= LastName #></li>" + "<li>Birth Date: <#= BirthDate #></li>" + "<li>Country: <#= Country #></li>" + "<li>City: <#= City #></li>" + "<li>Home Phone: <#= HomePhone #></li>" + "</ul>" )) // Handle the OnRowDataBound event in order to expand certain rows .ClientEvents(events => events.OnRowDataBound("onRowDataBound")) %> <script type="text/javascript"> function onRowDataBound(e) { var grid = $(this).data('tGrid'); // Expand the first row only if (grid.$rows().index(e.row) == 0) { grid.expandRow(e.row); } } </script>

public class HomeController : Controller { public ActionResult Index() { return View(); } [GridAction] public ActionResult _Employees() { return View(new GridModel(new NorthwindDataContext().Employees)); } }
Here is how the end result should look like (using the Forest skin):

![]() |
---|
The client detail template differs from the server detail template quite a bit:
![]() detailView.Template(e =>
{
%>
<ul>
<li>Name: <%= e.FirstName %> <%= e.LastName %></li>
<li>Birth Date: <%= e.BirthDate.Value.ToString("d") %></li>
<li>Country: <%= e.Country %></li>
<li>City: <%= e.City %></li>
<li>Home Phone: <%= e.HomePhone %></li>
</ul>
<%
})
![]() detailView.ClientTemplate( "<ul>" + "<li>Name: <#= FirstName #> <#= LastName #></li>" + "<li>Birth Date: <#= BirthDate #></li>" + "<li>Country: <#= Country #></li>" + "<li>City: <#= City #></li>" + "<li>Home Phone: <#= HomePhone #></li>" + "</ul>" )) |
Creating hierarchy using the client detail view template
You can easily add a grid in the server detail view template in order to create grid hierarchy. Here is how to show the Orders associated with each Employee:

<%= Html.Telerik().Grid<MvcApplication.Models.Employee>() .Name("Employees") .DataBinding(dataBinding => dataBinding.Ajax() // Specify the action method which returns the Employee objects .Select("_Employees", "Home")) .Columns(columns => { columns.Bound(e => e.FirstName); columns.Bound(e => e.LastName); columns.Bound(e => e.Title); }) .DetailView(detailView => detailView.ClientTemplate( // Define a grid bound to the Order object Html.Telerik().Grid<MvcApplication.Models.Order>() //Ensure the Name of each grid is unique .Name("Orders_<#= EmployeeID #>") .DataBinding(dataBinding => dataBinding.Ajax() // Specify the action method which returns the Orders for a particular Employee // Notice how the `EmployeeID` value is passed as the `id` argument using a client expression .Select("_Orders", "Home", new { id = "<#= EmployeeID #>"})) .Columns(columns => { columns.Bound(o => o.OrderID); columns.Bound(o => o.ShipName); columns.Bound(o => o.ShipAddress); columns.Bound(o => o.ShipCity); }) .Pageable() // The client detail view template requires a string so we are using the ToHtmlString method .ToHtmlString() )) // Handle the OnRowDataBound event in order to expand certain rows .ClientEvents(events => events.OnRowDataBound("onRowDataBound")) %> <script type="text/javascript"> function onRowDataBound(e) { var grid = $(this).data('tGrid'); // Expand the first row only if (grid.$rows().index(e.row) == 0) { grid.expandRow(e.row); } } </script>

public class HomeController : Controller { public ActionResult Index() { return View(); } [GridAction] public ActionResult _Employees() { return View(new GridModel(new NorthwindDataContext().Employees)); } [GridAction] public ActionResult _Orders(int id) { // Return the orders whose EmployeeID is equal to the action parameter return View(new GridModel(new NorthwindDataContext().Orders.Where(o => o.EmployeeID == id))); } }
Here is how the end result should look like (using the Web20 skin):

![]() |
---|
|
Nesting UI components in the server detail template

<%= Html.Telerik().Grid<Hierarchy.Models.Employee>() .Name("Employees") .DataBinding(dataBinding => dataBinding.Ajax() // Specify the action method which returns the Employee objects .Select("_Employees", "Home")) .Columns(columns => { columns.Bound(e => e.FirstName); columns.Bound(e => e.LastName); columns.Bound(e => e.Title); }) .DetailView(detailView => detailView.ClientTemplate( Html.Telerik().TabStrip() // Make the Name unique .Name("TabStrip_<#= EmployeeID #>") .SelectedIndex(0) .Items(items => { items.Add().Text("Orders").Content( // Define a grid bound to the Order object Html.Telerik().Grid<Hierarchy.Models.Order>() //Ensure the Name of each grid is unique .Name("Orders_<#= EmployeeID #>") .DataBinding(dataBinding => dataBinding.Ajax() // Specify the action method which returns the Orders for a particular Employee // Notice how the `EmployeeID` value is passed as the `id` argument using a client expression .Select("_Orders", "Home", new { id = "<#= EmployeeID #>" })) .Columns(columns => { columns.Bound(o => o.OrderID); columns.Bound(o => o.ShipName); columns.Bound(o => o.ShipAddress); columns.Bound(o => o.ShipCity); }) .Pageable() .ToHtmlString() ); items.Add().Text("Employee Details").Content( "<ul>" + "<li>Name: <#= FirstName #> <#= LastName #></li>" + "<li>Birth Date: <#= BirthDate #></li>" + "<li>Country: <#= Country #></li>" + "<li>City: <#= City #></li>" + "<li>Home Phone: <#= HomePhone #></li>" + "</ul>"); }) .ToHtmlString() )) %>
Here is how the end result should look like (using the Hay skin):

![]() |
---|
In this example we are using the Content(string value) methot because the TabStrip is defined in a client detail view template. If a client event of a nested UI is required - you should use the override which accepts string not Action. Right: ClientEvents(events => events.OnLoad("onLoad"))Wrong: ClientEvents(events => events.OnLoad(() => {%> alert('load'); <%}) |