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