Forms
EditForm and the built-in input components handle binding, validation state and submission for you.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 29, 2026
Learning objectives#
- Build a form with EditForm
- Use built-in input components
- Handle valid and invalid submissions
- Make forms work with static SSR
Explanation#
EditForm wraps a model and creates an EditContext that tracks which fields changed and whether they are valid.
Input components (InputText, InputNumber, InputSelect, InputDate, InputCheckbox, InputTextArea) bind with @bind-Value and add CSS classes for valid/invalid states.
OnValidSubmit runs only when validation passes; OnInvalidSubmit when it fails; OnSubmit lets you decide yourself.
In static SSR, give the form a FormName and receive the model with [SupplyParameterFromForm].
Code example: Add product form#
@page "/products/new"
@inject IProductService Products
@inject NavigationManager Nav
<EditForm Model="Model" FormName="add-product" OnValidSubmit="SaveAsync">
<DataAnnotationsValidator />
<ValidationSummary />
<label>Name <InputText @bind-Value="Model.Name" /></label>
<label>Price <InputNumber @bind-Value="Model.Price" /></label>
<label>Category
<InputSelect @bind-Value="Model.Category">
<option value="">Choose…</option>
<option>Computers</option>
<option>Accessories</option>
</InputSelect>
</label>
<button type="submit">Save</button>
</EditForm>
@code {
[SupplyParameterFromForm] private ProductForm Model { get; set; } = new();
private async Task SaveAsync()
{
await Products.CreateAsync(Model);
Nav.NavigateTo("/products");
}
}
Submitting an empty form lists the validation errors; a valid form saves the product and navigates to /products.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- EditForm binds to Model and is named so it works as a static SSR form.
- DataAnnotationsValidator applies the model’s [Required] and [Range] rules.
- Inputs bind with @bind-Value and get valid/invalid CSS classes.
- SaveAsync runs only when the model is valid.
Real-world use case#
Registration, checkout and admin create/edit screens — consistent validation and error display everywhere.
Common mistakes#
Plain inputs do not notify the EditContext, so validation state is not tracked. Use the Input* components.
Without FormName the posted form cannot be matched to the component.
Best practices#
- Use a dedicated form model (DTO)
- Prefer OnValidSubmit
- Disable the submit button while saving
- Re-validate on the server/API
Remember this#
EditForm + Input* components + validator.
OnValidSubmit only runs when valid.
Static SSR form = FormName + [SupplyParameterFromForm].
Practice exercise#
Your task: Add a multi-line Description field to the form.
Show solution
<label>Description <InputTextArea @bind-Value="Model.Description" rows="4" /></label>
Mini quiz#
Which callback runs only when the form passes validation?
Want more? Practise all Blazor MCQs · Blazor interview questions
My notes#
Saved in this browser.