Display templates
MVC has a bunch of handy helpers that we can use to create our views efficiently and effectively. One such helper is the display templates that are used within views.@Html.DisplayFor(e => e.Username)The
DisplayFor(Func<TModel, TValue> expression)
function uses the type of the property in the expression to display the property value. <!-- DisplayFor on string UserName = "daniel.imms" --> <span class="field-validation-valid" data-valmsg-for="UserName" data-valmsg-replace="true">daniel.imms</span>
Defining custom templates
We can override the default templates by placing our custom display templates into the pathViews/Shared/DisplayTemplates/<type>.cshtml
. They are structured like any MVC partial view. An example usage could be adding a dollar sign to the front of a decimal
's value. Model:
public class TestModel { public decimal Money { get; set; } }
Views/Shared/DisplayTemplates/decimal.cshtml
: @model decimal @{ IFormatProvider formatProvider = new System.Globalization.CultureInfo("en-US"); <span class="currency">@Model.ToString("C", formatProvider)</span> }View:
@model TestModel @Html.DisplayFor(e => e.Money)Output:
<span class="currency">$3.50</span>
UIHint attribute
To use a custom display template that isn't based on the name of the type, we can set aUIHint
attribute on the property. So we could make a 'Currency' display template instead of assuming that all decimals are dollar amounts. To do this we would simply rename ourdecimal.cshtml
file above to Currency.cshtml
and apply the UIHint
attribute to the model property like so: public class TestModel { [UIHint("Currency")] public decimal Money { get; set; } }
Editor templates
Editor templates can be overridden in the same way using theEditorFor
function and placing the custom templates inViews/Shared/EditorTemplates/<type>.cshtml
.Passing additional data
It may be necessary to provide more than just a property to the custom template. For example if we want to display a list of radio buttons with one of them selected. This could be achieved by passing in the list of options as 'view data' and having the property as anint?
which would represents the index of the selected option. MVC provides an overload that allows us to pass in this additional view data to the custom template, EditorFor(Func<TModel, TValue> expression, Object additionalViewData)
.Model:
public class UserModel { [UIHint("RadioButtonList")] public int? UserRole { get; set; } }Controller:
public class TestController : Controller { public ActionResult Test() { return View(new UserModel() { UserRole = 2 }); } }View:
@model UserModel @{ // In a real system we would get this list from the database List<SelectListItem> list = new List<SelectListItem>(); list.Add(new SelectListItem() { Text = "Admin", Value = "0" }); list.Add(new SelectListItem() { Text = "Project manager", Value = "1" }); list.Add(new SelectListItem() { Text = "User", Value = "2" }); } @Html.EditorFor(e => e.UserRole, new { List = list })
Views/Shared/EditorTemplates/RadioButtonList.cshtml
: @model int? @using System.Collections @using System.Web.Mvc; @{ var list = (List<SelectListItem>)ViewData["List"]; } <ul class="radio-list"> @foreach (var item in list) { <li> @{ var radioId = ViewData.TemplateInfo.GetFullHtmlFieldId(item.Value); var checkedClass = (item.Value == Model.ToString() ? "checked" : string.Empty); <input type="radio" id="@radioId" name="@ViewData.TemplateInfo.HtmlFieldPrefix" value="@item.Value" checked="@checkedClass" /> <label for="@radioId">@item.Text</label> } </li> } </ul>Output:
<ul class="radio-list"> <li> <input type="radio" id="UserRole_0" name="UserRole" value="0" checked="" /> <label for="UserRole_0">Admin</label> </li> <li> <input type="radio" id="UserRole_1" name="UserRole" value="1" checked="" /> <label for="UserRole_1">Project manager</label> </li> <li> <input type="radio" id="UserRole_2" name="UserRole" value="2" checked="checked" /> <label for="UserRole_2">User</label> </li> </ul>
Usage examples
- Format currency
- Format dates in a particular way
- Format credit card numbers
- Display a list of radio buttons or check boxes
- Add custom classes/IDs/structure to the output markup
Update:
Another article here on my series.
No comments:
Post a Comment