如何修改LabelFor在必填字段上显示星号?


71

我想为其创建扩展方法,如果需要的话HtmlHelper,允许我创建LabelFor一个属性显示星号。我怎样才能做到这一点?

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

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

有关标签标记帮助程序解决方案的信息,请参见stackoverflow.com/questions/41071757/…–
xhafan

Answers:


38

这是一篇博客文章,介绍了如何执行此操作。

为了给您一个从上面的站点修改而来的小示例(注意-我尚未对此进行编译/测试):

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年

@BrunoLM-不确定,尤其是在没有看到堆栈跟踪的情况下。(就像我说的那样-我在发布代码之前并没有实际测试过。我只是修改了博客中提供的内容。)
JasCav 2011年

如果您看到我在下面发布的内容,也可以通过lambda表达式执行此操作。
Adam Tuliper-MSFT 2011年

4
我花了整整一整天的时间发现,您必须使用@ Html.MyFor(m => m.Name)而不是@ MyNamespace.MyFor(m => m.Name)。因此,对于那些可能遇到相同问题的人,这是我的小贡献。;)
Tuco 2012年

这工作得很好,我只需要将方法名称更改为“ RequiredLabelFor”,因为原始名称一直解析为System.Web.Mvc.LabelFor()。谢谢!
议会

135

您可以仅通过CSS将星号添加到必填字段。

首先,为其创建一个CSS类:

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

这会将红色星号附加到具有“必需”类的任何元素上。

然后,在您看来,只需将新类添加到标签中即可:

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

更好的可能是自定义HTML Helper,它可以识别字段是否具有[Required]属性,如果有,则添加requiredCSS类。


6
不适用于我,但以下适用:@Html.LabelFor(m => m.Name, new { @class="required" })以及您建议的样式。不过,感谢您使我走上正确的道路。
曼弗雷德(Manfred)2012年

我在标签后的换行符上有一个红色的星号。如何将其附加在标签后而不是换行符上?
Kala J

卡拉,我用曼弗雷德(Manfred)的反馈纠正了我的回答。
罗杰·罗斯

@KalaJ我必须添加display: inline;样式以使星号保持同一行。
JuhaPalomäki'16

这对我来说非常有效,感谢您添加!
棱镜eyez83

24

我这样做是因为我的必填字段必须是动态的(在配置文件中定义)

在视图末尾添加:

    <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结果。
Paul DB

这是Renato答案的一种变体,只需在输入中设置常规MVC错误样式即可$('input[type=text]').each(function () { var req = $(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'); }); }
Paul DB

+1是因为将其添加到_Layout.cshtml主文件中,并且自动将整个项目中多个区域的数十个视图中的每个必填字段都添加了红色星号。我确实将第二行更改为...“ $('*')。each(function(){” ... ...,以便它将影响所需的密码,下拉框,单选框,输入文件等。
罗伯特·塔南鲍姆

4
好的答案,但仅将样式应用于input [type = text]元素。必需的属性也可以作为<select>,<textarea>或其他元素输出。考虑改用$('[[data-val-required]')选择器。
2013年

1
如果您如上所述使用$('[data-val-required]')选择器,请参考此答案,以避免在模型中未明确[必需]的某些字段中添加星号
aponzani 2014年

21

这是我基于Adam Tuliper答案的解决方案,但经过修改可与Bootstrap配合使用,并且还允许使用自定义属性

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" })

PS确保您不要忘记在视图中包括名称空间。


8
感谢您在代码的顶部放置正确的using语句。保存一些搜索对象的正确名称空间。
尼尔·门罗2014年

1
我经常在这里找到很棒的代码,但必须搜索正确的参考和用法。我以为有人会觉得有用!:-)
Maxime

如果我将MetadataType属性用于模型元数据,它将起作用吗?
Bimal Das

13

请在此处查看此帖子-应该包含您所需的大多数内容 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());
}

1
我认为最好在标签上添加一个类,然后通过CSS对其进行样式设置:
Daniel Bardi 2015年

@DanielBardi当然,如果就这么简单,您可以轻松地修改上面的内容-您仍然需要吐出一些元数据,说上面的内容是必需的:)
Adam Tuliper-MSFT 2015年

如果我将MetadataType属性用于模型元数据,它将起作用吗?
Bimal Das

4

使用助手将样式类添加到标签

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 : "*" }

4

我从其他一些帖子中总结了这一点:

它对我有用,因为labelfor后面是一个输入加上一个跨度(标签所针对的输入以及验证跨度)

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

2

基于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);
        }
    });
});

2

尽管这不需要修改LabelFor,但我认为这是最简单的,在ViewModel中只需要1行:

public class FooViewModel
{
   [Required(ErrorMessage = "Name is required")]
   [Display(Name ="Name*")]
   public string Name { get; set; }
}

Html.LabelFor(o => o.Name)

2

在MVC中使用多种字段类型最适合我

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


1

使用帮助程序扩展在保留内部化/翻译标签和html属性的必填字段(通过数据注释[必需]定义)之后添加修饰的glyphicon图标

1.创建文件夹“ Helpers”并添加一个新的控制器“ 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.您认为

@using WIPRO.Helpers

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

代替

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

希望能帮助到你 ;-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.