10
votes

This is for an ASP.NET MVC Core 1.1 web app.

I'd like a nice way of displaying a required field indicator (like a red * after the label) for fields in my model which have the [Required] attribute set.

Currently I have my labels on the form using the LabelTagHelper, like this:

<label asp-for="Surname" class="required"></label>

I have some CSS which adds the * symbol after my label based on the presence of the "required" class:

label.required:after {
    color: #A94442;
    content: ' *';
    display:inline;
}

This works. But of course if I change my model and add or remove a [Required] attribute for a field I have to make sure I manually go to the markup and make the corresponding change, adding or removing the "required" class for the label in question.

Can anyone help me with an elegant way to add the "required" class to a label based on the presence of the [Required] attribute on model rather than having to hardcode it into the cshtml?

Maybe a custom tag helper which inherits from LabelTagHelper? And uses reflection to see if the [Required] attribute is in the model field?

Or is there a better way?

2
did it help? if yes, could you make the answer as resolved?serge

2 Answers

9
votes

You can create a dedicated TagHelper to achieve this purpose:

[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class RequiredTagHelper : TagHelper
{
    private const string ForAttributeName = "asp-for";

    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression For { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (output == null)
            throw new ArgumentNullException(nameof(output));

        if (For.Metadata.IsRequired)
        {
            var existingClass = output.Attributes.FirstOrDefault(f => f.Name == "class");
            var cssClass = string.Empty;
            if (existingClass != null)
            {
                cssClass = $"{existingClass.Value} ";
            }

            cssClass += "required";
            output.Attributes.SetAttribute("class", cssClass);
        }
    }
}
2
votes

Suggestion:

Instead of just output.Attributes.Remove(existingClass);, maybe some verification in case the label doesn't have the attribute "class":

if(existingClass != null)
{
     output.Attributes.Remove(existingClass);
}