TagHelpers 根据验证属性为 LabelTagHelper 添加自定义 class [必需]

TagHelpers add custom class for LabelTagHelper based on validation attribute [Required]

在 Core MVC 中有一个新的概念作为标签助手。

我们之前可以创建自定义 html 帮助器,以根据 [Required].

等验证数据注释附加一些 classes

作为 TagHelpers arq 相当新的领域,我找不到足够的资源来实现以下目标:

这是视图模型:

    [Required]
    public Gender Gender { get; set; }

查看:

<label class="control-label col-md-3 required" asp-for="Gender"></label>

css:

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

输出:

但我不想在标签中手动添加所需的 css class。我应该能够以某种方式扩展 LabelTagHelper 以读取模型数据注释,如果它具有 [Required],则在标签元素中添加 required class。

谢谢,

是的,您可以通过继承 LabelTagHelper class 并首先将您自己的 class 添加到属性列表来轻松扩展它。

[HtmlTargetElement("label", Attributes = "asp-for")]
public class RequiredLabelTagHelper : LabelTagHelper
{
    public RequiredLabelTagHelper(IHtmlGenerator generator) : base(generator)
    {
    }

    public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (For.Metadata.IsRequired)
        {
            CreateOrMergeAttribute("class", "required", output);
        }

        return base.ProcessAsync(context, output);
    }

    private void CreateOrMergeAttribute(string name, object content, TagHelperOutput output)
    {
        var currentAttribute = output.Attributes.FirstOrDefault(attribute => attribute.Name == name);
        if (currentAttribute == null)
        {
            var attribute = new TagHelperAttribute(name, content);
            output.Attributes.Add(attribute);
        }
        else
        {
            var newAttribute = new TagHelperAttribute(
                name,
                $"{currentAttribute.Value.ToString()} {content.ToString()}",
                currentAttribute.ValueStyle);
            output.Attributes.Remove(currentAttribute);
            output.Attributes.Add(newAttribute);
        }
    }
}

对于 Will Ray 的回答,我想将覆盖 ProcessAsync 更改为:

public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)

{     

     var isRequired = For.Metadata.ValidatorMetadata.Any(x => 
                         x.GetType().Name.Equals("RequiredAttribute"));
     if (isRequired)
     {
          CreateOrMergeAttribute("class", "required", output);
     }

     return base.ProcessAsync(context, output);
}

因为 For.Metadata.IsRequired 对于布尔属性始终为真。

由于值和引用类型的处理方式不同,以下代码可能会有所帮助:

public override async Task ProcessAsync(TagHelperContext context,TagHelperOutput output)
{
    await base.ProcessAsync(context, output);

    if (RequiredAttributeExists(For.Metadata))
    {
        output.AddClass("required", HtmlEncoder.Default);
    }
}

private static bool RequiredAttributeExists(ModelMetadata metaData)
{
    if (metaData.ModelType.IsValueType)
    {
        return metaData.ValidatorMetadata.Any(x => x is RequiredAttribute);
    }
    else // not value type
    {
        return metaData.IsRequired;
    }
}