In Core MVC there is anew concept as Tag helpers.
We could previously create custom html helpers to attach some classes based on the validation data annotations such as [Required].
As TagHelpers arq quite new area I cannot find anough resources to achieve the following:
here is the view model:
[Required]
public Gender Gender { get; set; }
view:
<label class="control-label col-md-3 required" asp-for="Gender"></label>
css:
.required:after {
content: "*";
font-weight: bold;
color: red;
}
output:
But I don't want to manully add the required css class in the label. Somehow I shoudl be able to extend the LabelTagHelper to read model data annotations and if it has the [Required] then add required class in the label element.
Thanks,
Yup, you can extend this pretty easily by inheriting from the LabelTagHelper
class and adding in your own class to the attribute list first.
[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);
}
}
}
For answer by Will Ray, I'd like to make a change to the override ProcessAsync
as:
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);
}
Since For.Metadata.IsRequired
is always true for boolean properties.