EditForm - forms and validation in Blazor
Tags: blazor, beginners, dotnet, aspnetcore
Published: 2020-09-24 06:11:18

ASP.Net Core Blazor ships some great components to get building web forms quickly and easily. The **EditForm** component allows us to manage forms, validations, and form submission events.

Microsoft docs says, an **EditForm** "*Renders a form element that cascades an `EditContext` to descendants.*"

Let's see a Blazor EditForm in action,

```html
<EditForm Model="@employee" OnValidSubmit="@OnValidSubmit">
    <label>Employee Name :</label>
    <div>
        <InputText @bind-Value="@employee.EmployeeName" />
    </div>
    <label>Gender :</label>
    <div>
        <InputSelect @bind-Value="@employee.Gender"> 
            <option value="Select">--Select--</option>
            <option value="Male">Male</option>
            <option value="Female">Female</option>
            <option value="Other">Other</option>
         </InputSelect>
    </div>
    <label>DOB :</label>
    <div>
        <InputDate @bind-Value="@employee.DateOfBirth" />
    </div>
    <label>Department :</label>
    <div>
        <select @bind="@employee.DepartmentID"> 
            <option value=0>--Select--</option>
            <option value=1>Admin</option>
            <option value=2>HR</option>
            <option value=3>Payroll</option>
        </select>
    </div>
    <button type="submit" class="btn btn-success">
        @ButtonText
    </button>
</EditForm>

@code {
    [Parameter]
    public Employee employee { get; set; }
    [Parameter]
    public string ButtonText { get; set; } = "Save";
    [Parameter]
    public EventCallback OnValidSubmit { get; set; }
}

```

If we run this application in the browser you can see the rendered form with all other elements,


```html
<form>  
     <label>Employee Name :</label>
    <div> 
         <input class="valid"> 
    </div> 
     <label>Gender :</label>
    <div> 
         <select class="valid">  
             <option value="Select">--Select--</option>
             <option value="Male">Male</option>
             <option value="Female">Female</option>
             <option value="Other">Other</option>
         </select> 
    </div> 
     <label>DOB :</label>
    <div> 
         <input type="date" class="valid"> 
    </div> 
     <label>Department :</label>
    <div> 
        <select>  
            <option value="0">--Select--</option> 
            <option value="1">Admin</option> 
            <option value="2">HR</option> 
            <option value="3">Payroll</option> 
        </select> 
    </div> 
    <button type="submit" class="btn btn-success"> 
        Create Employee 
    </button> 
</form>
```
Here, The `EditForm` renders an HTML form element with `InputText` as `input type=text`, `InputSelect` as `select` and, `InputDate` as `input type=date`. Also notice that EditForm added a CSS class 'valid' to each input element. This has something to do with the validation.

You can also use any HTML elements like `input`, `select` etc. in EditForm as it renders an HTML form.

###EditForm Properties

In our example, `EditForm` has two attributes specified. `Model` and `OnValidSubmit`.

**Model** - Specifies the top-level model object for the form. Let me explain this,

Under the hood, EditForm manages the state of the form and any validation errors by storing it in an `EditContext` object. EditForm component instantiates **EditContext** for the model object specified in the Model attribute. In the above example `employee` object.

We can also specify the `EditContext` explicitly to an EditForm component by using the EditContext attribute instead of the Model attribute. 

```html
<EditForm EditContext="@EmployeeContext" OnSubmit="@OnSubmit">
</EditForm>
```
Here, we have to explicitly instantiate `EditContext` for `employee` object

```c#
@code {
    [Parameter]
    public Employee employee { get; set; }
    protected EditContext EmployeeContext { get; set; }
    protected override void OnInitialized()
    {
        EmployeeContext = new EditContext(employee);
    }

    [Parameter]
    public string ButtonText { get; set; } = "Save";
    [Parameter]
    public EventCallback OnSubmit { get; set; }   
}
```
>You can specify either a **Model or EditContext** but **not both**

Use the **Model** attribute to specify the form model object and it is sufficient to manage all standard form operations and validations. Use **EditContext** attribute only if you want to take more direct control over the form's `EditContext` object to explicitly fire a validation or to notify a field change etc.

![EditContext](https://dev-to-uploads.s3.amazonaws.com/i/20oow3p3sdbq9a1eg1nb.PNG)

Another attribute used in our example is **OnValidSubmit**. This is a callback/method that will be invoked when the form is submitted and the EditContext is determined to be valid. In addition to this, EditForm provides two other callback attributes,

**OnSubmit** callback will be invoked when the form is submitted, but here we have to explicitly validate the EditContext.

**OnInValidSubmit** callback will be invoked when the form is submitted and the EditContext is determined to be invalid.

###Form Validations 

We can enable validation for the entire form simply by adding the `<DataAnnotationsValidator />` component.

```html
<EditForm Model="@employee" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
</EditForm>
```
The validation will work according to the *DataAnnotations* specified in our model class properties  

```c#
public class Employee
{
     public int EmployeeID{get;set;}
     [Required]
     public string EmployeeName{get;set;}
     [Range(typeof(DateTime), "1/1/1970", "12/31/2000", ErrorMessage = "Value for {0} must be between {1} and {2}")]
     public DateTime DateOfBirth{get;set;}
     public Gender Gender{get;set;}
     public int DepartmentID{get;set;}
     public Department Department{get;set;}
}
```
With this [Required] attribute we’ve indicated that the user must enter an Employee Name and with the [Range] attribute we have specified the date range that should be entered.

We can show the validation summary by simply adding the `<ValidationSummary />` component or you can show the validation message for each input by using the `<ValidationMessage >` component

###Styling

You can style EditForm simply by adding a CSS class as normal. The form elements will be styled accordingly.

Let's see our example EditForm with all validation and styles added,

```html
<EditForm Model="@employee" OnValidSubmit="@OnValidSubmit">
    <DataAnnotationsValidator />
    <div class="form-group">
        <label>Employee Name :</label>
        <div>
            <InputText @bind-Value="@employee.EmployeeName" class="form-control col-sm-3" />
            <ValidationMessage For="@(() => employee.EmployeeName)" />
        </div>
    </div>
    <div class="form-group ">
        <div>
            <label>Gender :</label>
            <div>
                <InputSelect @bind-Value="@employee.Gender" class="form-control col-sm-3"> 
                   <option value="Select">--Select--</option>
                   <option value="Male">Male</option>
                   <option value="Female">Female</option>
                   <option value="Other">Other</option>
                </InputSelect>
                <ValidationMessage For="@(() => employee.Gender)" />
            </div>
        </div>
    </div>
    <div class="form-group ">
        <div>
            <label>DOB :</label>
            <div>
                <InputDate @bind-Value="@employee.DateOfBirth" class="form-control col-sm-3" />
                <ValidationMessage For="@(() => employee.DateOfBirth)" />
            </div>
        </div>
    </div>
    <div class="form-group ">
        <div>
            <label>Department :</label>
            <div>
                <select @bind="@employee.DepartmentID" class="form-control col-sm-3"> 
                   <option value=0>--Select--</option>
                   <option value=1>Admin</option>
                   <option value=2>HR</option>
                   <option value=3>Payroll</option>
                </select>
                <ValidationMessage For="@(() => employee.DepartmentID)" />
            </div>
        </div>
    </div>
    <button type="submit" class="btn btn-success">
        @ButtonText
    </button>
</EditForm>

@code {
    [Parameter]
    public Employee employee { get; set; }
    [Parameter]
    public string ButtonText { get; set; } = "Save";
    [Parameter]
    public EventCallback OnValidSubmit { get; set; }
}

```
Now when you run this in the browser, you can see our form elements nicely styled up. Submit the form to see the validation in action

![form](https://dev-to-uploads.s3.amazonaws.com/i/w1dnbizwxdgh2k0cr3ou.PNG)

And, the rendered HTML 

```html
<form>  
    <div class="form-group"> 
         <label>Employee Name :</label>
        <div> 
             <input class="form-control col-sm-3 invalid"> 
             <div class="validation-message">The EmployeeName field is required.</div> 
        </div> 
    </div> 
    <div class="form-group "> 
        <div> 
             <label>Gender :</label>
            <div> 
                 <select class="form-control col-sm-3 modified valid">  
                    <option value="Select">--Select--</option>
                    <option value="Male">Male</option>
                    <option value="Female">Female</option>
                    <option value="Other">Other</option>
                </select> 
            </div> 
        </div> 
    </div> 
    <div class="form-group "> 
        <div> 
             <label>DOB :</label>
            <div> 
                 <input type="date" class="form-control col-sm-3 invalid"> 
                 <div class="validation-message">Value for DateOfBirth must be between 1/1/1970 0:00:00 and 12/31/2000 0:00:00</div> 
            </div> 
        </div> 
    </div> 
    <div class="form-group "> 
        <div> 
             <label>Department :</label>
            <div> 
                <select class="form-control col-sm-3">  
                   <option value="0">--Select--</option> 
                   <option value="1">Admin</option> 
                   <option value="2">HR</option> 
                   <option value="3">Payroll</option> 
                </select> 
                  
            </div> 
        </div> 
    </div> 
    <button type="submit" class="btn btn-success"> 
        Create Employee 
    </button> 
</form>
```
If you look closely at the rendered HTML, you will notice the extra classes added by EditForm, 'valid', 'invalid' and, 'modified'. The class 'invalid' indicates that it's failed in form validation. You can add CSS style to this class for highlighting the invalid elements. In our example, bootstrap is doing this for us. For any modified element, a 'modified' CSS class will be added.

###Summery

**EditForm** is pretty useful in creating web forms that keep the values in your model in sync with the values entered in the UI with out of the box validation support. But it doesn't stop you from creating your own form components in Blazor and implement custom logic for validations. EditForm is designed in such a way that you can easily implement any form validation you like. if you don't want to use DataAnnotation you can use any available validation components like [FluentValidation](https://github.com/FluentValidation/FluentValidation) 
or write a custom validation component.

If you wish to see how to use this Blazor EditForm in a working example, please read my previous post [Blazor Server CRUD App Using Visual Studio Code](https://dev.to/rineshpk/blazor-server-crud-app-using-visual-studio-code-2b2g). You can find the sample application source code [here](https://github.com/rineshpk/BlazorServerCRUD)