I have created a default MVC 3 project (using razor), in order to demonstrate an issue.
On the login page, there is a line:
@Html.TextBoxFor(m => m.UserName)
if I change this to:
@Html.TextBoxFor(m => m.UserName, new { title = "ABC" })
Then the it is rendered as (with a title attribute):
<input data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" title="ABC" type="text" value="" />
However, if I make it an EditorFor:
@Html.EditorFor(m => m.UserName, new { title = "ABC" })
Then it gets rendered (without a title attribute) as:
<input class="text-box single-line" data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" type="text" value="" />
So in summary, the title attribute is lost when I use EditorFor.
I know that the second parameter for TextBoxFor is called htmlAttributes, and for EditorFor it is additionalViewData, however I've seen examples where EditorFor can render attributes supplied with this parameter.
Can anyone please explain what I am doing wrong, and how I can have a title attribute when using EditorFor?
TextBoxFor: It will render like text input html element corresponding to specified expression. In simple word it will always render like an input textbox irrespective datatype of the property which is getting bind with the control. EditorFor: This control is bit smart.
The TextBoxFor() HTML Helper method is a strongly typed extension method. It generates an element of <input type=”text”> for the model property which needs to be specified using a lambda expression. The TextBoxFor() HTML Helper method binds the specified model object property to the input element.
EditorFor() extension methods generate HTML elements based on the data type of the model object's property. The following table list the data types and releted HTML elements: DataType. Html Element. string.
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.
I think I found a little nicer solution to it. EditorFor takes in additionalViewData as a parameter. If you give it a parameter named "htmlAttributes" with the attributes, then we can do interesting things with it:
@Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "span4", maxlength = 128, required = true, placeholder = "Email Address", title = "A valid email address is required (i.e. [email protected])" } })
In the template (in this case, EmailAddress.cshtml) you can then provide a few default attributes:
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, Html.MergeHtmlAttributes(new { type = "email" }))
The magic comes together through this helper method:
public static IDictionary<string, object> MergeHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes) { var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes") ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"]) : new RouteValueDictionary(); if (htmlAttributes != null) { foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes)) { var key = property.Name.Replace('_', '-'); if (!attributes.ContainsKey(key)) { attributes.Add(key, property.GetValue(htmlAttributes)); } } } return attributes; }
Of course you could modify it to render the attributes as well if you are doing raw HTML:
public static MvcHtmlString RenderHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes) { var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes") ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"]) : new RouteValueDictionary(); if (htmlAttributes != null) { foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes)) { var key = property.Name.Replace('_', '-'); if (!attributes.ContainsKey(key)) { attributes.Add(key, property.GetValue(htmlAttributes)); } } } return MvcHtmlString.Create(String.Join(" ", attributes.Keys.Select(key => String.Format("{0}=\"{1}\"", key, htmlHelper.Encode(attributes[key]))))); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With