2011-05-09 148 views
59

我想爲HtmlHelper創建一個擴展方法,它允許我創建一個LabelFor屬性,在它後面顯示一個星號(如果它是必填字段)。我怎樣才能做到這一點?如何修改LabelFor以在必填字段上顯示星號?

public class Foo 
{ 
    [Required] 
    public string Name { get; set; } 
} 

Html.LabelFor(o => o.Name) // Name* 

回答

36

這裏是一個blog post描述如何做到這一點。

爲了給你一個小例子從網站上面修改(注意 - 我還沒有編譯/測試此):

namespace HelpRequest.Controllers.Helpers 
{ 
    public static class LabelExtensions 
    { 
     public static MvcHtmlString Label(this HtmlHelper html, string expression, string id = "", bool generatedId = false) 
     { 
      return LabelHelper(html, ModelMetadata.FromStringExpression(expression, html.ViewData), expression, id, generatedId); 
     } 

     [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")] 
     public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string id = "", bool generatedId = false) 
     { 
      return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData), ExpressionHelper.GetExpressionText(expression), id, generatedId); 
     } 

     internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, string id, bool generatedId) 
     { 
      string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last(); 
      if (String.IsNullOrEmpty(labelText)) 
      { 
       return MvcHtmlString.Empty; 
      } 
      var sb = new StringBuilder(); 
      sb.Append(labelText); 
      if (metadata.IsRequired) 
       sb.Append("*"); 

      var tag = new TagBuilder("label"); 
      if (!string.IsNullOrWhiteSpace(id)) 
      { 
       tag.Attributes.Add("id", id); 
      } 
      else if (generatedId) 
      { 
       tag.Attributes.Add("id", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName) + "_Label"); 
      } 

      tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); 
      tag.SetInnerText(sb.ToString()); 

      return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal)); 
     } 
    } 
} 
+2

'ModelMetadata.FromStringExpression(expression,html.ViewData)'用這個我可以檢查'meta.IsRequired'並做我想要的。感謝你的回答。 – BrunoLM 2011-05-09 18:24:02

+0

@BrunoLM - 不確定,特別是沒有看到堆棧跟蹤。 (就像我說的 - 我在發佈之前沒有真正測試過這些代碼,我只是修改了博客提供的內容。) – JasCav 2011-05-09 18:24:21

+0

如果您看到我在下面發佈的內容,也可以從lambda表達式中進行此操作。 – 2011-05-09 18:28:36

12

這裏看到這個帖子 - 應包含大多數的你所需要的 http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Creating-tooltips-using-data-annotations-in-ASPNET-MVC.aspx

public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression) 
{ 
    var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 

    string htmlFieldName = ExpressionHelper.GetExpressionText(expression); 
    string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last(); 

    if (metaData.IsRequired) 
     labelText += "<span class=\"required-field\">*</span>"; 

    if (String.IsNullOrEmpty(labelText)) 
     return MvcHtmlString.Empty; 

    var label = new TagBuilder("label"); 
    label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); 

    label.InnerHtml = labelText; 
    return MvcHtmlString.Create(label.ToString()); 
} 
+0

我認爲這是最好添加一個類的標籤,然後風格它六一個CSS: – 2015-10-14 04:34:54

+0

@DanielBardi當然,你可以很容易地修改上述,如果這就是你想要的 - 你仍然需要一些東西來吐出元數據說它是必需的,這是上面顯示:) – 2015-10-16 07:26:56

+0

它會工作,如果我使用MetadataType屬性爲模型元數據? – 2017-08-09 10:38:35

16

我做了,那是因爲我的必填字段必須是動態的(在配置中定義文件)

添加在您查看的末尾:

<script type="text/javascript"> 
     $('input[type=text]').each(function() { 
      var req = $(this).attr('data-val-required'); 
      if (undefined != req) { 
       var label = $('label[for="' + $(this).attr('id') + '"]'); 
       var text = label.text(); 
       if (text.length > 0) { 
        label.append('<span style="color:red"> *</span>'); 
       } 
      } 
     }); 
    </script> 
+3

+ +1爲更簡單(雖然承認更脆弱)的方式來達到要求。自定義HtmlHelper是一個更加核心的,更好的解決方案,但我不喜歡使用反射來確定真正的IsRequired結果。 – 2012-11-02 00:03:17

+0

下面是Renato的答案的一個變體,它簡單地在輸入上設置常規的MVC錯誤樣式: '$('input [type = text]')。each(function(){var 0q = $(this).attr 'data-val-required'); if(undefined!= req){if($(this).val()==='') $(this).addClass('input-validation-error' ); $(this).change(function(){ if($(this).val()==='') $(this).addClass('input-validation-error'); else $(this).removeClass('input-validation-error'); }); }' }); – 2012-11-02 00:22:31

+0

+1,因爲在_Layout.cshtml主文件中添加此項,並自動在整個項目的多個區域中的幾十個視圖中的每個必需字段都帶有小紅色星號。我改變了第二行閱讀...「$('*')。each(function(){」...以便它會影響所需的密碼,下拉框,廣播框,輸入文件等 – 2013-04-04 18:07:06

99

您可以完全通過CSS添加一個星號必填字段。

首先,創建一個CSS類爲它:

.required:after 
{ 
    content: "*"; 
    font-weight: bold; 
    color: red; 
} 

這將紅色星號追加到任何元素與「必需的」類。

然後,在你看來,只需將新類添加到您的標籤:

@Html.LabelFor(m => m.Name, new { @class="required" }) 

更妙的可能是一個自定義HTML幫手辨別如果字段有[必需]屬性,如果是這樣,添加了「所需的」CSS類。

+6

沒有爲我工作,但以下做法:' @ Html.LabelFor(m => m.Name,new {@ class =「required」})'加上你建議的樣式。謝謝但是,讓我走上正確的道路。 – Manfred 2012-09-17 06:29:08

+0

我得到一個紅色的星號,在我的標籤後面換行。我如何才能將它追加到我的標籤後面而不是換行符上? – 2015-06-04 15:54:02

+0

卡拉,我用曼弗雷德的反饋改正了我的答案。 – 2015-06-05 17:04:32

17

這裏是基於Adam Tuliper's answer我的解決方案,但修飾引導工作,也讓定製的使用屬性

using System; 
using System.Linq; 
using System.Web.Mvc; 
using System.Linq.Expressions; 
using System.ComponentModel; 


public static class RequiredLabel 
{ 
    public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes) 
    { 
     var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 

     string htmlFieldName = ExpressionHelper.GetExpressionText(expression); 
     string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last(); 

     if (metaData.IsRequired) 
      labelText += "<span class=\"required\">*</span>"; 

     if (String.IsNullOrEmpty(labelText)) 
      return MvcHtmlString.Empty; 

     var label = new TagBuilder("label"); 
     label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); 

     foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes)) 
     { 
      label.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true); 
     } 

     label.InnerHtml = labelText; 
     return MvcHtmlString.Create(label.ToString()); 
    } 

} 

然後,我把它從我的觀點是這樣的:

@Html.RequiredLabelFor(model => model.Category, new { @class = "control-label col-md-3" }) 

附:確保你不要忘記在你的視圖中包含你的名字空間。

+7

感謝您將正確的使用語句放在代碼的頂部。保存一些搜索適當的對象名稱空間。 – 2014-06-18 15:50:30

+1

我經常在這裏找到優秀的代碼,但必須搜索正確的引用和使用。我認爲有些人會覺得它有用! :-) – Maxime 2014-07-25 20:53:59

+0

如果我爲模型元數據使用MetadataType屬性,它會起作用嗎? – 2017-08-09 10:38:14

3

使用幫手樣式類添加到標籤

public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes) 
{ 
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
    var resolvedLabelText = metadata.DisplayName ?? metadata.PropertyName; 
    if (!metadata.IsRequired) 
    { 
     return html.LabelFor(expression, resolvedLabelText, htmlAttributes); 
    } 

    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 
    if (attributes == null) 
    { 
     return html.LabelFor(expression, resolvedLabelText, htmlAttributes); 
    } 

    const string requiredClass = "required-label"; 
    if (attributes.ContainsKey("class")) 
    { 
     var classList = attributes["class"].ToString().Split(' ').ToList(); 
     classList.Add(requiredClass); 
     attributes["class"] = string.Join(" ", classList); 
    } 
    else 
    { 
     attributes.Add("class", requiredClass); 
    } 

    return html.LabelFor(expression, resolvedLabelText, attributes); 
} 

然後你就可以風格類:

它的工作原理爲:

.required-label::after { content : "*" } 
2

我從一些其他職位步履蹣跚了一起因爲labelfor後面跟着一個輸入加一個範圍(標籤的輸入和驗證範圍)

input[data-val-required]+span:before { 
    content: "*"; 
    font-weight: bold; 
    color: red; 
    position:relative; 
    top:-34px; 
    left:-12px; 
    font-size:14pt; 
} 
1

根據Renato Saito的上述回答以及註釋,以及添加$(document).ready和檢查以確保我們不添加多個星號(我在某些我出於某種原因域),我有這樣的:

// Add asterisks to required fields 
$(document).ready(function() { 
    $("[data-val-required]").each(function() { 
     var label = $('label[for="' + $(this).attr("id") + '"]'); 
     var asterisksHtml = '<span style="color:red">&nbsp;*</span>'; 
     if (label.text().length > 0 && label.html().indexOf(asterisksHtml) === -1) { 
      label.append(asterisksHtml); 
     } 
    }); 
}); 
1

添加裝飾glyphicon圖標爲必填字段後(使用輔助擴展維護都internalizations /翻譯標籤和HTML屬性通過數據註解[必填])定義

1.創建文件夾「助手」並添加一個新的控制器「Helper.cs」

using System; 
using System.ComponentModel; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Web.Mvc; 

namespace WIPRO.Helpers 
{ 
    public static class Helpers 
    { 
     public static MvcHtmlString LabelForRequired<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string translatedlabelText, object htmlAttributes) 
     { 
      var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 

      string htmlFieldName = ExpressionHelper.GetExpressionText(expression); 
      string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last(); 

      if (metaData.IsRequired) 
      { 
       labelText = translatedlabelText + "<span class=\"required\" style=\"color:orange;\"> <span style=\"font-size: 0.4em; vertical-align: super;\" class=\"glyphicon glyphicon-asterisk\" data-unicode=\"270f\"></span></span>"; 

      } 
      else 
      { 
       labelText = translatedlabelText; 

      } 

      if (String.IsNullOrEmpty(labelText)) 
       return MvcHtmlString.Empty; 

      var label = new TagBuilder("label"); 
      label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName)); 

      foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes)) 
      { 
       label.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true); 
      } 

      label.InnerHtml = labelText; 
      return MvcHtmlString.Create(label.ToString()); 

     } 

    } 

} 

2.在代替

 @Html.LabelFor(model => model.Test,"Translated text", htmlAttributes: new { @class = "control-label col-md-2" }) 

視圖

@using WIPRO.Helpers 

     @Html.LabelForRequired(model => model.Test,"Translated text", htmlAttributes: new { @class = "control-label col-md-2" }) 

希望它可以幫助;-)