How can I override the @Html.LabelFor template?
Solution 1
You'd do this by creating your own HTML helper.
http://www.asp.net/mvc/tutorials/creating-custom-html-helpers-cs
You can view the code for LabelFor<> by downloading the source for ASP.Net MVC and modify that as a custom helper.
Answer added by balexandre
public static class LabelExtensions
{
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
return LabelFor(html, expression, new RouteValueDictionary(htmlAttributes));
}
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
if (String.IsNullOrEmpty(labelText))
{
return MvcHtmlString.Empty;
}
TagBuilder tag = new TagBuilder("label");
tag.MergeAttributes(htmlAttributes);
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
TagBuilder span = new TagBuilder("span");
span.SetInnerText(labelText);
// assign <span> to <label> inner html
tag.InnerHtml = span.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
}
Solution 2
I expanded upon balealexandre's answer and added in the ability to specify HTML to include both before and after your label text. I added a bunch of method overloads and comments. I hope this helps folks!
Also snagged information from here: Html inside label using Html helper
namespace System.Web.Mvc.Html
{
public static class LabelExtensions
{
/// <summary>Creates a Label with custom Html before the label text. Only starting Html is provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Func<object, HelperResult> startHtml)
{
return LabelFor(html, expression, startHtml, null, new RouteValueDictionary("new {}"));
}
/// <summary>Creates a Label with custom Html before the label text. Starting Html and a single Html attribute is provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <param name="htmlAttributes">A single Html attribute to include.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Func<object, HelperResult> startHtml, object htmlAttributes)
{
return LabelFor(html, expression, startHtml, null, new RouteValueDictionary(htmlAttributes));
}
/// <summary>Creates a Label with custom Html before the label text. Starting Html and a collection of Html attributes are provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <param name="htmlAttributes">A collection of Html attributes to include.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, Func<object, HelperResult> startHtml, IDictionary<string, object> htmlAttributes)
{
return LabelFor(html, expression, startHtml, null, htmlAttributes);
}
/// <summary>Creates a Label with custom Html before and after the label text. Starting Html and ending Html are provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <param name="endHtml">Html to follow the label text.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Func<object, HelperResult> startHtml, Func<object, HelperResult> endHtml)
{
return LabelFor(html, expression, startHtml, endHtml, new RouteValueDictionary("new {}"));
}
/// <summary>Creates a Label with custom Html before and after the label text. Starting Html, ending Html, and a single Html attribute are provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <param name="endHtml">Html to follow the label text.</param>
/// <param name="htmlAttributes">A single Html attribute to include.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Func<object, HelperResult> startHtml, Func<object, HelperResult> endHtml, object htmlAttributes)
{
return LabelFor(html, expression, startHtml, endHtml, new RouteValueDictionary(htmlAttributes));
}
/// <summary>Creates a Label with custom Html before and after the label text. Starting Html, ending Html, and a collection of Html attributes are provided.</summary>
/// <param name="startHtml">Html to preempt the label text.</param>
/// <param name="endHtml">Html to follow the label text.</param>
/// <param name="htmlAttributes">A collection of Html attributes to include.</param>
/// <returns>MVC Html for the Label</returns>
public static MvcHtmlString LabelFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, Func<object, HelperResult> startHtml, Func<object, HelperResult> endHtml, IDictionary<string, object> htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
//Use the DisplayName or PropertyName for the metadata if available. Otherwise default to the htmlFieldName provided by the user.
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
if (String.IsNullOrEmpty(labelText))
{
return MvcHtmlString.Empty;
}
//Create the new label.
TagBuilder tag = new TagBuilder("label");
//Add the specified Html attributes
tag.MergeAttributes(htmlAttributes);
//Specify what property the label is tied to.
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
//Run through the various iterations of null starting or ending Html text.
if (startHtml == null && endHtml == null) tag.InnerHtml = labelText;
else if (startHtml != null && endHtml == null) tag.InnerHtml = string.Format("{0}{1}", startHtml(null).ToHtmlString(), labelText);
else if (startHtml == null && endHtml != null) tag.InnerHtml = string.Format("{0}{1}", labelText, endHtml(null).ToHtmlString());
else tag.InnerHtml = string.Format("{0}{1}{2}", startHtml(null).ToHtmlString(), labelText, endHtml(null).ToHtmlString());
return MvcHtmlString.Create(tag.ToString());
}
}
}
Solution 3
LabelFor is an extension method (static) and therefore cannot be overridden. You'd need to create your own Html Helper Extension method to achieve what you require.
balexandre
Father (x3), Husband (x1), Dedicated, Friendly. Web, Windows and Mobile developer (mostly .NET and NodeJs). Photographer by hobby, Windsurfer by passion. Born in Portugal (in 1977),happily married to a beautiful Romanian gal (since 2005) and living in Denmark (since 2006) 😊 P.S. My Simpson character was designed by a Fiverr.com user.
Updated on July 05, 2022Comments
-
balexandre almost 2 years
I have a simple field form
<div class="field fade-label"> @Html.LabelFor(model => model.Register.UserName) @Html.TextBoxFor(model => model.Register.UserName) </div>
and this results in:
<div class="field fade-label"> <label for="Register_UserName">Username (used to identify all services, from 4 to 30 chars)</label> <input type="text" value="" name="Register.UserName" id="Register_UserName"> </div>
but I want that
LabelFor
code append a<span>
inside so I can end up having:<label for="Register_UserName"> <span>Username (used to identify all services, from 4 to 30 chars)</span> </label>
How can I do this?
All examples use
EditorTemplates
but this is aLabelFor
. -
balexandre over 13 yearsGot it, added the final code to my question for anyone to copy/paste/use. Thanks for the heads up.
-
Linkgoron over 13 yearsEditor templates CAN be "overriden", although they TOO are static methods.
-
Darren Lewis over 13 yearsWe're not talking about Editor templates here. An Editor template is a partial view discovered through convention. It has nothing to do with overrides or static declaration of an extension method.
-
Linkgoron over 13 yearsYes, but when someone sees LabelFor, and then sees that it's similar to EditorFor he MIGHT think that it, too, can be overiden by convention. That's exactly what the OP asked. This has nothing to do with method overloading and static methods.
-
reaper_unique about 10 yearsI used this extension method as a start, but as it doesn't override the LabelFor method with the parameter fieldName I updated it a bit.
-
Ruchan over 9 yearsHow do i solve the Ambigious invocation error when using this. now there are two LabelFor methods one from the default MVC and this.
-
HaBo over 6 years@Ruchan did you ever get this fixed?
-
Ruchan over 6 yearsHad to rename my own helper with different name.