.NET Core required field indicator
Asked Answered
D

2

10

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?

Deportment answered 11/2, 2017 at 18:52 Comment(1)
did it help? if yes, could you make the answer as resolved?Tina
O
9

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);
        }
    }
}
Overcheck answered 11/8, 2017 at 6:56 Comment(5)
As Joao said, you should check whether the existing class is null before trying to remove it cs if(existingClass != null) { output.Attributes.Remove(existingClass); } Twosome
Thanks for the heads up, I've edited my answer. Instead of removing then adding the class attribute, I now use the .SetAttribute method that does the same thing.Maid
how should we use it? a short example would be coolTina
@Serge your model class (injected in your view via the @model directive) should have a property with the [Required] attribute, then in your view : <label asp-for="@Model.MyRequiredField"></label>Maid
@Overcheck see my version, inheriting from LabelTagHelper in the end of this OP stackoverflow.com/q/66256829/961631Tina
S
2

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);
}   
Sternick answered 23/1, 2020 at 14:59 Comment(1)
Welcome to Stack Overflow! This appears to be a commentary about the accepted answer, and not a direct answer itself. There's nothing wrong with suggesting an alternative solution to one already offered, but editing your answer to make it more standalone would improve your post's quality and make is less likely for it to be downvoted or removed.Furlough

© 2022 - 2025 — McMap. All rights reserved.