DEV Community

Cover image for EditForm - forms and validation in Blazor
rinesh
rinesh

Posted on

EditForm - forms and validation in Blazor

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,

<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; }
}

Enter fullscreen mode Exit fullscreen mode

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

<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>
Enter fullscreen mode Exit fullscreen mode

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.

<EditForm EditContext="@EmployeeContext" OnSubmit="@OnSubmit">
</EditForm>
Enter fullscreen mode Exit fullscreen mode

Here, we have to explicitly instantiate EditContext for employee object

@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; }   
}
Enter fullscreen mode Exit fullscreen mode

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

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.

<EditForm Model="@employee" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
</EditForm>
Enter fullscreen mode Exit fullscreen mode

The validation will work according to the DataAnnotations specified in our model class properties

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;}
}
Enter fullscreen mode Exit fullscreen mode

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,

<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; }
}

Enter fullscreen mode Exit fullscreen mode

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

And, the rendered 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>
Enter fullscreen mode Exit fullscreen mode

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
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. You can find the sample application source code here

Top comments (0)