How to use the Html.EditorFor method
This post will cover the following points (aprox. reading time 15mins):
- What is the Html.EditorFor method?
- Simple EditorFor example
- Extending EditorFor with templates based on Data Type (ie. Decimal)
- Extending EditorFor with templates based on Model Attribute (ie. DateTime with picker)
What is the Html.EditorFor method?
Microsoft defines the Html.EditorFor
method as follows (EditorFor on MSDN):
The EditorFor method is used to generate MVCHtmlString mark-up depending on the data type of the expression passed into it.
Simply put, the Html.EditorFor
method allows the developer to retain control over the display of form elements by data type (ie. string, boolean, int…etc) or model attribute at a global level rather than at an individual view level. This allows for cleaner ASP markup and easily scalable form controls.
Simple EditorFor example
The following example is a simple implementation of the Html.EditorFormethod
. For the following Model class:
public class ViewModel
{
public string MyString { get; set; }
public decimal MyDecimal { get; set; }
public bool MyBool { get; set; }
public DateTime MyDateTime { get; set; }
}
Each individual output element could be rendered using the following syntax:
<%: Html.TextBoxFor(o => o.MyString) %>
<%: Html.TextBoxFor(o => o.MyDecimal) %>
<%: Html.CheckBoxFor(o => o.MyBool) %>
<%: Html.TextBoxFor(o => o.MyDateTime) %>
Alternatively you could implement the exact same front-end functionality using the Html.EditorFor
method, as follows:
<%: Html.EditorFor(o => o.MyString) %>
<%: Html.EditorFor(o => o.MyDecimal) %>
<%: Html.EditorFor(o => o.MyBool) %>
<%: Html.EditorFor(o => o.MyDateTime) %>
This method is a great example of how Html.EditorFor
will modify the output depending on the datatype of the underlying object property (ie. Html.EditorFor(o => o.MyBool)
). The resulting output for either method will look something similar to the following image:
Extending EditorFor with templates based on Data Type (ie. Decimal)
The Html.EditorFor
method can be extended with the use of templates for specific data types at a global level. As an example, I may wish to display all decimal values with 3 digits after the decimal point and comma thousands separator (ie. 1,020.300) instead of the default (ie. 1020.30). I can achieve this by defining a decimal editor template which will reside in ./Views/Shared/EditorTemplates/
folder of our MVC application project. Create a new file Decimal.ascx
with the following content, note that the filename maps to the data type:
<%@ Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<decimal?>"
%>
<%: Html.TextBox(
string.Empty,
Model.HasValue ? Model.Value.ToString("#,0.000#") : string.Empty
)
%>
The Inherits="System.Web.Mvc.ViewUserControl<decimal?>"
defines the data type that the template expects to receive, which in this scenario is a nullable decimal. The following lines check that the Model has a value and returns the value formatted as specified earlier. If no value is provided then it will be displayed as an empty text box. The resulting output will look as follows:
Extending EditorFor with templates based on Model Attributes
The above example allows us to modify the editor output for all model elements of a specific data type, however what happens if we only want a sub-set of model elements to have a modified editor output? This can be done through the UIHint
model attribute, which acts as a template override parameter for your model element. Update the ViewModel
class we created earlier to look like the following:
[UIHint("DateTimePicker")]
public DateTime MyDateTime { get; set; }
Please note that you will need include the System.ComponentModel.DataAnnotations
library at the start of your file to use this annotation.
Then create a new Editor Template named DateTimePicker.ascx
with the following content:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<% var uid = Guid.NewGuid(); %>
<%: Html.TextBox(
string.Empty,
Model.HasValue ? Model.Value.ToString("MMM d, yyyy") : string.Empty,
new { @id = uid }
)
%>
<script type="text/javascript">
$("#<%: uid %>").datepicker({ dateFormat: 'M d, yy' });
</script>
The above code works in a similar way as the Decimal.ascx
we created earlier, but with a few additions. There is now a uid
variable being generated, which is used for the id of the textbox, there is then javascript code which uses the uid
to bind to the textbox and display the datepicker.