Skip to content

Create a reusable ErrorSummary component #57

@s-laugh

Description

@s-laugh

Most applications would need an Error Summary in their forms. The main challenge would be how are errors populated to this... and how is the translation handled.

One option that I'm using is a TagHelper

using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace CESG_SCEE.WebUI.Helpers
{
    [HtmlTargetElement("gcds-error-summary", Attributes = "model-state,model-type")]
    public class GcdsErrorSummaryTagHelper : TagHelper
    {
        [HtmlAttributeName("model-state")]
        public required ModelStateDictionary ModelState { get; set; }

        [HtmlAttributeName("model-type")]
        public required Type ModelType { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (ModelState == null || ModelState.IsValid || ModelType == null)
                return;

            var errorSummary = new Dictionary<string, string>();
            var genErrCount = 0;

            foreach (var entry in ModelState)
            {
                var errorMessages = entry.Value.Errors
                    .Select(error => error.ErrorMessage)
                    .ToList();

                foreach (var errorMessage in errorMessages)
                {
                    if (string.IsNullOrEmpty(entry.Key))
                    {
                        errorSummary[$"GenError:{++genErrCount}"] = errorMessage;
                    }
                    else
                    {
                        //TODO error links need to be fixed
                        errorSummary[$"#{SanitizeForHtmlId(entry.Key)}"] = $"{ViewModelHelper.GetDisplayName(entry.Key, ModelType)} - {errorMessage}";
                    }
                }
            }

            if (errorSummary.Count > 0)
            {
                var json = JsonSerializer.Serialize(errorSummary);
                output.Attributes.SetAttribute("error-links", json);
            }
        }

        private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(100);
        private static readonly Regex HtmlIdSanitizer = new(@"[^a-zA-Z0-9\-_:.]", RegexOptions.Compiled, RegexTimeout);

        private static string SanitizeForHtmlId(string input)
            => HtmlIdSanitizer.Replace(input ?? string.Empty, "_");


    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions