Form Validations Made Easy in Blazor
Tags: csharp, dotnet, beginners, webdev
Published: 2023-10-02 15:28:14

## Introduction
At the core of every application, be it a web application, mobile or desktop application, data is entered, processed and displayed in a useful way. Now since data is essential, we can't just have our applications accepting any form of data on face-value, what if the entered data is simply nothing?
So how is data entered into applications from end users? you guessed it; **Forms**.

Now it's true that we can verify the data before it gets stored in the application's database, it makes more sense to check it before it gets sent to the server therefore reducing the amounts of trips made to our brave server; Show some love for the server ❤️

With form validations, we can check the data upon pressing **Submit**, with some validations specified on the data model the form is dealing with, we can identify breaches in the data before it gets sent over to the server. So, instead of submitting the form data, waiting until the server notices that **Oh, this data looks unusable and it cannot be stored**, then get the validation errors back from the server so that we can show the user that what they typed in, simply doesn't work, we can port over this task, to happen directly on the client.

## Let's Get Started, Shall We?
In most websites, you'll have DTOs or Data Transfer Objects, each is responsible for a task, such as creating/editing/getting certain resource, if that's the case, you would apply data validations on the ones related to creating a resource, or requests such as Sign in/Sign up. However, the concept taught here, works on everything, with everything. So wether you're using **Fluent Validations** or **Data Annotations**, the changes are very minor.

For simplicity, I'll create a local data model called **User**, with enough properties to showcase how we can handle form validations in Blazor in a nice way. 

> 💡 **Info:** The same methodology applies for Blazor WASM and Blazor Server, so feel free to use whatever project type you like.

Let's begin by looking at our data model that we'll be using throughout this post:

```csharp

namespace FormValidationsDemo.Models;

public class User
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string? Email { get; set; }
    public string? PasswordConfirmation { get; set; }
    public string? Password { get; set; }
}

```

Now I'll add some data annotations to the model, feel free to add your custom validations if you'd like, but I'll try keeping it simple yet almost realistic:

```csharp

using System.ComponentModel.DataAnnotations;

namespace FormValidationsDemo.Models;

public class User
{
    [Required(ErrorMessage = "Your first name is required")]
    public string? FirstName { get; set; }

    [Required(ErrorMessage = "Your last name is required")]
    public string? LastName { get; set; }

    [Required(ErrorMessage = "Your email is required")]
    [EmailAddress(ErrorMessage = "Please enter a valid email address")]
    public string? Email { get; set; }

    [Required(ErrorMessage = "Your password is required")]
    public string? Password { get; set; }

    [Required(ErrorMessage = "The password confirmation is required")]
    [Compare("Password", ErrorMessage = "Password and password confirmation don't match")]
    public string? PasswordConfirmation { get; set; }

}

```

Keeping it simple, we could've gone crazier with `MaxLength`, `MinLength`, `RegularExpression` and more, but that's sufficient.
If you didn't catch up, let me briefly explain to you
- We're ensuring all properties cannot be null.
- The email address has to look like an email address (i.e contains an @ symbol).
- Password confirmation must match the specified password.

Now that our data model is ready, we'll now build our form that should mockingly, sign up a new user.

I have some starter code inside `Index.razor`, which creates a card in the center of the page, and creates an EditForm

```html

<div class="h-screen flex justify-center items-center bg-gray-100">
    <div class="form-card">
        <h1 class="text-3xl font-bold mb-5">Sign Up</h1>

        <EditForm Model="userModel" OnValidSubmit="MockUserSignUp">
            
        </EditForm>
    </div>
</div>

```
```csharp

@code {
    private User userModel = new();

    private void MockUserSignUp()
    {
        Console.WriteLine("You have been signed up! I Promise ;-)");
    }
}

```

> 💡 **NOTE:** I'm using Tailwind Css to style the page elements, but please don't worry about the classes being applied as the page styles isn't what we're here for.

I want to talk to you about this thing: `EditForm`
This is a special form that we use in Blazor instead of the typical `<form>` element that's used almost everywhere, why you may ask? Well, let's answer this
The `EditForm` is used in Blazor when we want to bind a form to a data model, check for validations, and do a certain action, either when just submitted, OR, when submitted with valid data.
This component automatically generates something known as an `EditContext`, which is essentially a class, that's responsible for storing information regarding the ongoing editing process on the form, like the values being changed. 

> 💡 **NOTE:** The `EditContext` can be created manually in case you wanted to add some custom logic, but we're not going to go down this rabbit hole in this post.

Now I'll be adding the form fields inside of `EditForm`, again, don't worry about the Tailwind classes there:

```html

<EditForm Model="userModel" OnValidSubmit="MockUserSignUp">
    <div class="form-group">
        <label class="field-label">First Name</label>
        <InputText @bind-Value="userModel.FirstName" class="text-input" />
    </div>

    <div class="form-group">
        <label class="field-label">Last Name</label>
        <InputText @bind-Value="userModel.LastName" class="text-input" />
    </div>

    <div class="form-group">
        <label class="field-label">Email</label>
        <InputText type="email" @bind-Value="userModel.Email" class="text-input" />
    </div>

    <div class="form-group">
        <label class="field-label">Password</label>
        <InputText type="password" @bind-Value="userModel.Password" class="text-input" />
    </div>

    <div class="form-group">
        <label class="field-label">Password Confirmation</label>
        <InputText type="password" @bind-Value="userModel.PasswordConfirmation" class="text-input" />
    </div>

    <div class="form-group">
        <button type="submit" class="primary-btn">Sign up</button>
    </div>
</EditForm>

```

Now that's our form ready, and everything is bound to the userModel object that we created earlier, we're set to check for validations, but before we do, if you were to run the project, click **Sign up**, with all the fields empty, the form would still submit, as you can see in the following image:


![Invalid form submission](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kreygefbo8geqwdn6inz.png)

It works, but it shouldn't, right? Well, let's fix it!

After the opening tag of the `EditForm` component, add this line:
`<DataAnnotationsValidator />`
Rerun the project now, hit **Sign up**, and it won't work anymore. Why?
That line we added right here, will check on with the `EditContext` and use a technique called **Reflection** to check wether the values of the form fields, which are bound to the object model, do NOT violate the rules specified for the data model (The data annotations attributes we added to our User class), if any single property fails the check, the form will not submit. Pay close attention to the fact that we're using the EditForm's `OnValidSubmit` event, if we were to use the other event ,`OnSubmit`, pressing the button would complete the submission even if the data is not valid.

> 💡 **NOTE:** If you were using **Fluent Validations**, you wouldn't use `<DataAnnotationsValidator />`, instead, it would be something like `<FluentValidationsValidator />`, now please note I'm not sure about the exact name of the component, but you can reference the package's documentation for further details.

Now, below the line we just added, add another line to add another component:
`<ValidationSummary class="text-red-600 font-light" />`

Now submitting an empty form, would look like this:

![Using the validation summary component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bfstx8i9t1wgd9n3gir.png)

As you can see, we're getting a summary of all the validation rules that we've violated. (Quite a lot to be honest).

You can try filling up some data that violets other rules like password and password confirmation mismatch so that you can see the validations we applied being displayed to the user.

## Improving the overall look of the form
The validations summary we saw earlier, put bluntly, looks ugly as hell, like in comparison with the look of our form, it's just too horrible to stay like that. Enter `<ValidationMessage/>`, this bad boy right here, is our ticket for making our form look dope.

This component only displays the validation message for a specific form field, instead of a whole summary.

To make use of this, below the `<InputText>` component, add this line:

```html

<div class="form-group">
    <label class="field-label">First Name</label>
    <InputText @bind-Value="userModel.FirstName" class="text-input" />
    <ValidationMessage For="(() => userModel.FirstName)" class="text-red-600 font-light mb-2"/>
</div>

```

Using the `For` parameter of this component, we're essentially telling it which property to display the validation message for, the rest is for styling purposes.

Now as a practice task, add the same component to the rest of the form fields, and make sure to point them each to its respective property.

## Final Code Result
The `EditForm` should contain the following code after doing your practice task:

```html

<EditForm Model="userModel" OnValidSubmit="MockUserSignUp">
    <DataAnnotationsValidator />
    <div class="form-group">
        <label class="field-label">First Name</label>
        <InputText @bind-Value="userModel.FirstName" class="text-input" />
        <ValidationMessage For="(() => userModel.FirstName)" class="text-red-600 font-light" />
    </div>

    <div class="form-group">
        <label class="field-label">Last Name</label>
        <InputText @bind-Value="userModel.LastName" class="text-input" />
        <ValidationMessage For="(() => userModel.LastName)" class="text-red-600 font-light" />
    </div>

    <div class="form-group">
        <label class="field-label">Email</label>
        <InputText type="email" @bind-Value="userModel.Email" class="text-input" />
        <ValidationMessage For="(() => userModel.Email)" class="text-red-600 font-light" />
    </div>

    <div class="form-group">
        <label class="field-label">Password</label>
        <InputText type="password" @bind-Value="userModel.Password" class="text-input" />
        <ValidationMessage For="(() => userModel.Password)" class="text-red-600 font-light" />
    </div>

    <div class="form-group">
        <label class="field-label">Password Confirmation</label>
        <InputText type="password" @bind-Value="userModel.PasswordConfirmation" class="text-input" />
        <ValidationMessage For="(() => userModel.PasswordConfirmation)" class="text-red-600 font-light" />
    </div>

    <div class="form-group">
        <button class="primary-btn">Sign up</button>
    </div>
</EditForm>

```

Now submitting the form, should look something like this:

![Using the validation message component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grs0i67qdvtf0hnwznay.png)

That's so much more elegant and nice looking than the whole summary being thrown all in one place.

## Conclusion
We've covered a lot during this article, initially we introduced why form validations is necessary and a must-do process, we then created our data model, applied data annotations attributes to it, then created our `EditForm` component so that we could work with validations and see how the different components such as `DataAnnotationsValidator` can affect the overall behavior of the form, along side the form events, `OnSubmit` and `OnValidSubmit`. Finally, we used both techniques for displaying the validation messages to our end user and we saw which one is clearly better. However, as long as you're invested in making a nice looking form, then rendering out individual validation messages just beneath their respective fields is obviously the better choice, but in case looks don't bother you, then the first technique we covered would be an easy go-to choice for your project.

I hope you learned something new at the end of this article, and thanks for baring with me lengthy times!








 


...