Adding html covers in LabelFor - MVC 3

I have a complex form that should be used by both javascript and non-javascript users. My application is .NET MVC 3.

There are many fields on the form that need to be completed if they answer in a certain way to the previous question. If javascript is enabled, I can show or hide the corresponding question based on user interaction. Without javascript, I would like to add more detailed information to the question label itself, because by default all questions are displayed (like filling out a paper version of the form).

Ideally, I would like the label to be something like:

<label><span class="non-js">If you were a smoker, when</span><span class="js">When</span> did you stop smoking?</label> 

That way I can turn off the corresponding text in CSS (I hope the firmware can handle this).

So javascript users get:

 When did you stop smoking? 

and non-javascript users get:

 If you were a smoker, when did you stop smoking? 

My question is how I will deal with this, since LabelFor helpers do not allow html in line.

Update

Sorry, I forgot one key bit of information, because my shortcut is currently filling out the annotation in the model [Display (Name = "When did you stop smoking?")]. Idelly I would like to keep this here and have something like:

 [Display(JS = "When", NonJS = "If you were a smoker, when", Both="did you stop smoking?")] 

Is it possible?

Update 2

Well, that’s what I have so far. This is my attribute:

 public class MultipleDisplayNameAttribute : Attribute, IMetadataAware { public string CustomerDisplayName { get; set; } public string CustomerJSAlternative { get; set; } public string CustomerNonJSAlternative { get; set; } public void OnMetadataCreated(ModelMetadata metadata) { string jsPart; string nonJsPart; jsPart = (CustomerJSAlternative != null) ? String.Format("<span class='spnJs'>{0}</span>", CustomerJSAlternative) : ""; nonJsPart = (CustomerNonJSAlternative != null) ? String.Format("<span class='spnNonJs'>{0}</span>", CustomerNonJSAlternative) : ""; metadata.DisplayName = String.Format("{0}{1}{2}", jsPart, nonJsPart, CustomerDisplayName); } } 

Unfortunately, I'm stuck right now, as it is displayed on the screen without restrictions. that is, on the screen it looks like this:

 <span class="non-js">If you were a smoker, when</span><span class="js">When</span> did you stop smoking? 

Is there a way to change the displayName metadata property to handle this?

Update 3 and solution

Using answers and http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx I was able to get the solutions that I got after:

My attribute:

 public class MultipleDisplayNameAttribute : Attribute, IMetadataAware { public string CustomerDisplayName { get; set; } public string CustomerJSAlternative { get; set; } public string CustomerNonJSAlternative { get; set; } public void OnMetadataCreated(ModelMetadata metadata) { metadata.AdditionalValues["JS"] = (CustomerJSAlternative != null) ? String.Format("<span class='spnJs'>{0}</span>", CustomerJSAlternative) : ""; metadata.AdditionalValues["NoJS"] = (CustomerNonJSAlternative != null) ? String.Format("<span class='spnNonJs'>{0}</span>", CustomerNonJSAlternative) : ""; metadata.DisplayName = CustomerDisplayName; } } 

My helper:

  public static MvcHtmlString JsAndNonJsCheckFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); HtmlString jsLabel = new HtmlString(""); HtmlString noJsLabel = new HtmlString(""); string htmlFieldName = ExpressionHelper.GetExpressionText(expression); string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last(); if (String.IsNullOrEmpty(labelText)) return MvcHtmlString.Empty; if(metadata.AdditionalValues.ContainsKey("JS")) jsLabel = new HtmlString((string)metadata.AdditionalValues["JS"]); if (metadata.AdditionalValues.ContainsKey("NoJS")) noJsLabel = new HtmlString((string)metadata.AdditionalValues["NoJS"]); TagBuilder tagBuilder = new TagBuilder("label"); tagBuilder.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); tagBuilder.InnerHtml = String.Format("{0}{1}{2}", jsLabel, noJsLabel, labelText); return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal)); } 

The work is done (in the end!) Thanks for the help!

+6
source share
2 answers

The current issue is how LabelFor works. This is the decompiled source code for LabelFor (from MVC2. The actual source is probably more enjoyable and freely available for download):

  public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { return LabelExtensions.LabelHelper((HtmlHelper) html, ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, html.ViewData), ExpressionHelper.GetExpressionText((LambdaExpression) expression)); } internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName) { string str = metadata.DisplayName; if (str == null) { string propertyName = metadata.PropertyName; if (propertyName == null) str = Enumerable.Last<string>((IEnumerable<string>) htmlFieldName.Split(new char[1] { '.' })); else str = propertyName; } string innerText = str; if (string.IsNullOrEmpty(innerText)) return MvcHtmlString.Empty; TagBuilder tagBuilder = new TagBuilder("label"); tagBuilder.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); tagBuilder.SetInnerText(innerText); return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal); } } 

You can basically copy this code, change the method name and change the second last line of code:

 tagBuilder.InnerHtml(innerText); 

And you will have a working solution that does not elude your HTML.

+4
source

You can write your own LabelFor extension for Html. I would recommend this, since you could pass js and non-js text as parameters instead of writing HTML over and over. Here's the main label type helper:

 using System; namespace MvcApplication1.Helpers { public class LabelHelper { public static string LabelJsNonJs(this HtmlHelper helper, string target, string nonJs, string js, string commonText) { return String.Format("<label for='{0}'><span class='non-js'>{1}</span><span class='js'>{2}</span>{3}</label>", target, nonJs, js, commonText); } } } 

You can use this in your views by adding the use of MvcApplication1.Helpers for your namespace.

See http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx for more information on creating a LabelFor type helper (a bit more complicated, and I don’t have much time).

+5
source

Source: https://habr.com/ru/post/899620/


All Articles