Creating a Custom Validation Message Component for Blazor Forms
Tags: blazor, webdev, csharp, dotnet
Published: 2020-07-06 22:08:55

---
title: Creating a Custom Validation Message Component for Blazor Forms
published: true
date: 2020-06-30 08:14:07 UTC
tags: Blazor,WebDev,CSharp,DotNet
canonical_url: https://chrissainty.com/creating-a-custom-validation-message-component-for-blazor-forms/
---

 ![Creating a Custom Validation Message Component for Blazor Forms](https://chrissainty.com/content/images/2020/06/creating-a-custom-validation-message-component-for-blazor-forms.jpg)

As some of you may know, I'm a big fan of Tailwind CSS. If you've not heard of Tailwind before then please checkout my previous posts about it which can be found [here](https://dev.to/chrissainty/integrating-tailwind-css-with-blazor-using-gulp-part-1-4k6g) and [here](https://dev.to/chrissainty/integrating-tailwind-css-with-blazor-using-gulp-part-2-435i). The reason I mention this is because when I was using it on a recent Blazor project, I hit a bit of a snag. I wanted to style my validation messages using Tailwinds utility classes, but I couldn't add them to the component. This is because the `ValidationMessage` component adds a hard-coded class which can't be added to or overriden.

<!--kg-card-begin: markdown-->
```
builder.OpenElement(0, "div");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", "validation-message");
builder.AddContent(3, message);
builder.CloseElement();

```
<!--kg-card-end: markdown-->

The full source can be viewed [here](https://github.com/dotnet/aspnetcore/blob/master/src/Components/Web/src/Forms/ValidationMessage.cs), but as you can see in the snippet above, while the component supports passing additional attributes, the component will always override any `class` attribute that is supplied.

I could've added a wrapper `div` around each usage of `ValidationMessage` and added my classes there, but that felt like a clunky solution. I've also seen several people in the community asking about customising the output of the `ValidationSummary` component. So I thought this would be a good opportunity to come up with a better way.

In this post, I'm going to show how you can create a `ValidationMessage` component with customisable UI. I'll start by showing a more simplistic approach and then show a more robust and reusable solution.

## How does ValidationMessage work?

Before we get into the solutions, I wanted to quickly cover how the standard `ValidationMessage` works.

The default component is pretty compact weighing in at about 100 lines of code. It accepts a cascaded `EditContext` and adds an event handler for the `OnValidationStateChanged` event. All this handler does is call `StateHasChanged` whenever the event fires.

It also creates a `FieldIdentifier` based on whichever model property has been specified via the `For` parameter. This is then used when calling the `GetValidationMessages` method on the `EditContext`. This method will return all of the current validation error messages for the given `FieldIdentifier`. Any messages returned are then rendered.

In summary, the componet does three things:

- Listens for changes to the validation state
- Retrieves any validation messages for the model property specified
- Displays the messages on screen

Now we understand what the original component does, let's move on to the solutions.

## Creating a simple replacement

The first option, which was pretty quick to build, was largly a modified version of the original component.

The default component caters for a lot of potential scenarios, things like dynamically changing `EditContext`'s or updates to the `For` parameter. Therefore there's a lot of code which is checking and caching values to support this and be as efficient as possible.

However, my use case was very straightforward, just a standard form which wouldn't have anything dynamically changing. This mean't that I could do away with a good amount of code. The result is the following.

<!--kg-card-begin: markdown-->
```
@using System.Linq.Expressions

@typeparam TValue
@implements IDisposable

@foreach (var message in EditContext.GetValidationMessages(_fieldIdentifier))
{
    <div class="@Class">
        @message
    </div>
}

@code {
    [CascadingParameter] private EditContext EditContext { get; set; }

    [Parameter] public Expression<Func<TValue>> For { get; set; }
    [Parameter] public string Class { get; set; }

    private FieldIdentifier _fieldIdentifier;

    protected override void OnInitialized()
    {
        _fieldIdentifier = FieldIdentifier.Create(For);
        EditContext.OnValidationStateChanged += HandleValidationStateChanged;
    }

    private void HandleValidationStateChanged(object o, ValidationStateChangedEventArgs args) => StateHasChanged();

    public void Dispose()
    {
        EditContext.OnValidationStateChanged -= HandleValidationStateChanged;
    }
}

```
<!--kg-card-end: markdown-->

I implemented the same fundamental behavor as the original component, I created a `FieldIdentifier` based on the model property defined via the `For` parameter. Registered a handler for the `OnValidationStateChanged` event on `EdiContext`. I also unregistered it to avoid any memory leaks by implementing `IDisposable`.

In my markup, I then output any validation messages as per the original component, but with one simple difference. I removed the hard-coded CSS applied and added a `Class` parameter. Now I could provide any classes I wanted to apply on a case by case basis. Here's an example of usage.

<!--kg-card-begin: markdown-->
```
<CustomValidationMessage For="@(() => _model.FirstName)"
                         Class="mt-2 sm:ml-4 font-semibold text-red-600" />

```
<!--kg-card-end: markdown-->

This implementation resolved the original issue, I could now use my Tailwind CSS classes to style my validation messages without any issues. Job done, right?

For my immediate problem, yes. But it got me thinking about some of those comments from the community I mentioned in the introduction. In those comments, developers were asking about changing the HTML that was rendered, not just adding custom CSS classes. This solution doesn't help with that problem. This lead me to create my second solution.

## ValidationMessageBase<T> for ultimate customisation

I really love the approach the Blazor team took with building the input components for forms. Providing us with `InputBase<T>` is great as we can focus on building custom UI, which is what needs to be changed in 99% of cases, while the boilerplate of integrating with the form and validation system is taken care of.

Wouldn't it be great if there was something like that for validation messages as well...?

### Creating ValidationMessageBase<T>

By creating a base class for validation messages, as per the design of the input components, it would give developers the freedom to tweak the UI output to their exact needs. Here's the code.

<!--kg-card-begin: markdown-->
```
public class ValidationMessageBase<TValue> : ComponentBase, IDisposable
{
    private FieldIdentifier _fieldIdentifier;

    [CascadingParameter] private EditContext EditContext { get; set; }
    [Parameter] public Expression<Func<TValue>> For { get; set; }
    [Parameter] public string Class { get; set; }

    protected IEnumerable<string> ValidationMessages => EditContext.GetValidationMessages(_fieldIdentifier);

    protected override void OnInitialized()
    {
        _fieldIdentifier = FieldIdentifier.Create(For);
        EditContext.OnValidationStateChanged += HandleValidationStateChanged;
    }

    private void HandleValidationStateChanged(object o, ValidationStateChangedEventArgs args) => StateHasChanged();

    public void Dispose()
    {
        EditContext.OnValidationStateChanged -= HandleValidationStateChanged;
    }
}

```
<!--kg-card-end: markdown-->

This is essentially the logic from the code block in the first solution, except I've added a property which returns the current validation messages instead of calling the `GetValidationMessages` method directly on the `EditContext`. This is purely to make the developer experience a little nicer when implementing markup for the validation messages.

With this base class I can implement the same markup as I had for the first solutions really easily.

<!--kg-card-begin: markdown-->
```
@typeparam TValue
@inherits ValidationMessageBase<TValue>

@foreach (var message in ValidationMessages)
{
    <div class="@Class">
        @message
    </div>
}

```
<!--kg-card-end: markdown-->

And if I want to implement something different in a future project all I need to do is create a new derived component.

<!--kg-card-begin: markdown-->
```
@typeparam TValue
@inherits ValidationMessageBase<TValue>

@if (ValidationMessages.Any())
{
    <ul class="validation-errors">
        @foreach (var message in ValidationMessages)
        {
            <li class="validation-error-message">
                @message
            </li>
        }
    </ul>
}

```
<!--kg-card-end: markdown-->
## Summary

In this post, I've show a limitation with the default `ValidationMessage` component which comes with Blazor, specifically, the inability to customise the markup it produces. I've shown two potential solutions.

The first is a modified version of the original component. The hard-coded styling was removed and replaced with a `Class` parameter allowing CSS classes to be specified per usage.

The second solution was based on the design of Blazors input components. A base class was used to abstract away the boilerplate code, allowing developers to focus on creating the specific markup they require, for ultimate flexability.