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

问题描述 投票:0回答:14

我想为

HtmlHelper
创建一个扩展方法,它允许我创建一个
LabelFor
属性,如果它是必填字段,则在其后面显示一个星号。我怎样才能做到这一点?

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

Html.LabelFor(o => o.Name) // Name*
c# asp.net-mvc-3
14个回答
146
投票

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

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

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

这将为任何具有“required”类的元素附加一个红色星号。

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

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

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

required
CSS 类。


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

26
投票

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

在视图末尾添加:

    <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>

22
投票

这是我的解决方案,基于 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" })

附注确保您不要忘记在视图中包含您的命名空间。


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());
}

5
投票

使用 helper 将样式类添加到标签

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;
}

4
投票

虽然这不需要修改 LabelFor,但这是我能想到的最简单的,只需要 ViewModel 中的 1 行:

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

Html.LabelFor(o => o.Name)

3
投票

根据 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
投票

在具有多种字段类型的 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 属性的辅助扩展在必填字段(通过数据注释定义 [必需])后添加装饰字形图标

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

希望有帮助;-)


1
投票

发布通用解决方案:

以下是使用 Bootstrap 的通用格式:

<div class="form-group row">
    <label class="col-md-3 label-control" asp-for="FacilityCode"></label>
    <div class="col-md-9">
        <input asp-for="FacilityCode" class="form-control" placeholder="@Localizer["Facility Code"]" />
        <span asp-validation-for="FacilityCode" class="text-danger"></span>
    </div>
</div>

这里是TagHelper默认生成的代码:

<div class="form-group row">
  <label class="col-md-3 label-control" for="FacilityCode">Example Label </label>
  <div class="col-md-9">
       <input class="form-control" placeholder="Facility Code" type="text" data-val="true" data-val-length="The field Institution (Community) must be a string with a maximum length of 5." data-val-length-max="5" data-val-required="The Institution (Community) field is required." id="FacilityCode" maxlength="5" name="FacilityCode" value="12345">
       <span class="text-danger field-validation-valid" data-valmsg-for="FacilityCode" data-valmsg-replace="true"></span>
  </div>
</div>

我需要的是将

<span style="color:red;">*</span>
附加到所有必填字段,而不是在任何地方使用
TagHelper

// append red star to required fields
$(document).ready(function () {
    $('input[data-val-required]')
        .closest(".form-group")
        .find("label.label-control")
        .append("<span style='color:red;'>*</span>");
});

0
投票

我想创建一个在需要属性时显示星号的标签。但不知何故,即使

metadata.IsRequired
属性已设置并在模型验证中工作,
[Required]
属性始终返回 false。所以我用了
AssociatedMetadataTypeTypeDescriptionProvider

public static MvcHtmlString CustomLabelFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null)
{
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var descriptor = new AssociatedMetadataTypeTypeDescriptionProvider(metadata.ContainerType).GetTypeDescriptor(metadata.ContainerType).GetProperties().Find(metadata.PropertyName, true);
    var required = (new List<Attribute>(descriptor.Attributes.OfType<Attribute>())).OfType<RequiredAttribute>().FirstOrDefault();

    //get the normal labelfor
    var label = htmlHelper.LabelFor(expression, htmlAttributes);

    //create the extra span with the asterix in there is a required property
    if (required != null)
    {
        var span = new TagBuilder("span");
        span.MergeAttribute("class", "text-danger font-weight-bold");

        //render the span
        StringBuilder sb = new StringBuilder();
        sb.Append(span.ToString(TagRenderMode.StartTag));
        sb.Append("*");
        sb.Append(span.ToString(TagRenderMode.EndTag));

        return MvcHtmlString.Create(label.ToHtmlString() + " " + sb.ToString());
    }
    else
    {
        return label;
    }
}

用法

@Html.CustomLabelFor(m => m.Title)

0
投票

我正在与

TagHelper

分享另一种简单的方法
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace MyTestProject.Helpers;

[HtmlTargetElement("label", Attributes = "asp-for")]
public class RequiredFieldTagHelper : TagHelper
{
    public override int Order => 1;

    [HtmlAttributeName("asp-for")]
    public ModelExpression For { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        ArgumentNullException.ThrowIfNull(context);
        ArgumentNullException.ThrowIfNull(output);

        var metadata = For.Metadata;

        var isRequired = metadata.ValidatorMetadata
            .Any(m => m is RequiredAttribute);

        if (isRequired)
        {
            var asterisk = new TagBuilder("span");
            asterisk.AddCssClass("text-danger required-field-marker");
            asterisk.InnerHtml.Append("*");
            output.PostContent.AppendHtml(asterisk);
        }
    }
}

完成后,我们可以将

AssemblyName
添加到
_ViewImports.cshtml
文件中,
MyTestProject
是我项目的
<AssemblyName>

@addTagHelper *, MyTestProject

我们也可以添加 CSS 更改

.required-field-marker {
    margin-left: 4px;
    color: firebrick;
}

.required-field-note {
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.75rem;
    font-style: italic;
}
© www.soinside.com 2019 - 2024. All rights reserved.