Blazor Forms
Blazor makes building interactive web UI with .NET easy. Handling forms is a fundamental part of web development, and Blazor provides a robust and declarative way to manage form input and validation.
Introduction to Blazor Forms
Blazor forms leverage HTML form elements and Blazor's data binding and event handling capabilities to create dynamic and user-friendly forms. You can easily bind input elements to component parameters, handle form submission, and implement client-side and server-side validation.
Core Concepts
- Data Binding: Use directives like
@bind
to synchronize component parameters with form input values. - Event Handling: Respond to form events like
onsubmit
or input events using Blazor's event handling syntax (e.g.,@onchange
,@oninput
). - Validation: Implement validation rules to ensure data integrity before submission. Blazor integrates with standard HTML5 validation attributes and offers custom validation logic.
Creating a Simple Form
Let's create a basic contact form with name and email fields.
ContactForm.razor
<EditForm Model="@_contactInfo" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label for="name">Name:</label>
<InputText id="name" @bind-Value="_contactInfo.Name" />
</div>
<div class="form-group">
<label for="email">Email:</label>
<InputText id="email" @bind-Value="_contactInfo.Email" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</EditForm>
@code {
private ContactInfo _contactInfo = new ContactInfo();
public class ContactInfo
{
public string Name { get; set; }
public string Email { get; set; }
}
private void HandleValidSubmit()
{
// Process the valid form data
Console.WriteLine($"Submitting: Name={_contactInfo.Name}, Email={_contactInfo.Email}");
}
}
In this example:
<EditForm>
is the main container for your form.Model
binds the form to a data object.OnValidSubmit
is an event that fires only when the form's validation passes.<DataAnnotationsValidator />
enables validation using data annotations (more on this later).<ValidationSummary />
displays a summary of validation errors.<InputText>
is a Blazor component for text input, bound using@bind-Value
.
Validation
Blazor offers powerful validation capabilities, primarily through data annotations and the <DataAnnotationsValidator>
component.
Using Data Annotations
Decorate your model properties with attributes from the System.ComponentModel.DataAnnotations
namespace.
ContactInfo.cs
(for enhanced validation)
using System.ComponentModel.DataAnnotations;
public class ContactInfo
{
[Required(ErrorMessage = "Name is required.")]
[StringLength(50, ErrorMessage = "Name cannot be longer than 50 characters.")]
public string Name { get; set; }
[Required(ErrorMessage = "Email is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public string Email { get; set; }
}
Now, when you use <DataAnnotationsValidator />
in your <EditForm>
, these attributes will be used for validation.
<ValidationMessage>
To display validation messages for individual fields, use the <ValidationMessage>
component:
<div class="form-group">
<label for="name">Name:</label>
<InputText id="name" @bind-Value="_contactInfo.Name" />
<ValidationMessage For="() => _contactInfo.Name" />
</div>
Input Components
Blazor provides a set of built-in input components that work seamlessly with <EditForm>
and data binding:
<InputText>
: For text input.<InputNumber<T>>
: For numeric input.<InputDate<T>>
: For date input.<InputCheckbox>
: For checkboxes.<InputRadioGroup<T>>
: For radio buttons.<InputSelect<T>>
: For dropdown lists.
Example: Dropdown List
<div class="form-group">
<label for="country">Country:</label>
<InputSelect id="country" @bind-Value="_userProfile.Country">
<option value="" disabled>-- Select Country --</option>
@foreach (var country in AvailableCountries)
{
<option value="@country">@country</option>
}
</InputSelect>
<ValidationMessage For="() => _userProfile.Country" />
</div>
@code {
// ... other properties ...
public UserProfile _userProfile = new UserProfile();
public List<string> AvailableCountries { get; set; } = new List<string> { "USA", "Canada", "Mexico", "UK" };
public class UserProfile { public string Country { get; set; } }
}
Custom Input Components
For more complex input scenarios, you can create your own custom input components by implementing the IComponentBinding
interface or by using <InputBase>
.
Form Submission and Processing
The OnValidSubmit
event is crucial for handling form data after successful validation. Inside this handler, you can:
- Send the data to a server API.
- Update application state.
- Navigate the user to another page.
- Display a success message.
Handling Submission State
It's good practice to provide feedback during submission, such as disabling the submit button and showing a loading indicator.
<EditForm Model="..." OnValidSubmit="@HandleValidSubmit">
@* ... form fields ... *@
<button type="submit" disabled="@_isSubmitting">
@if (_isSubmitting)
{
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span> Submitting...</span>
}
else
{
<span>Save Changes</span>
}
</button>
</EditForm>
@code {
private bool _isSubmitting = false;
private async Task HandleValidSubmit()
{
_isSubmitting = true;
try
{
// Simulate API call
await Task.Delay(2000);
// Process form data
}
finally
{
_isSubmitting = false;
}
}
}
Styling Forms
Blazor forms can be styled using standard CSS. The built-in Blazor input components render standard HTML elements, allowing you to apply your styles easily.
<InputText>
, <InputNumber>
, etc., for better integration with the Blazor framework and validation system.
Common Form Layouts
You can arrange form elements using CSS classes like Flexbox or Grid. Here's a simple example of grouped form elements:
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Email</label>
<InputText id="inputEmail4" @bind-Value="_user.Email" />
<ValidationMessage For="() => _user.Email" />
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Password</label>
<InputText id="inputPassword4" type="password" @bind-Value="_user.Password" />
<ValidationMessage For="() => _user.Password" />
</div>
</div>
<style>
.form-row { display: flex; gap: 15px; margin-bottom: 15px; }
.form-group { flex: 1; }
.form-group label { display: block; margin-bottom: 5px; font-weight: 500; }
.form-group input { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; }
.form-group .validation-message { color: red; font-size: 0.9em; }
</style>
@code {
public class User {
public string Email { get; set; }
public string Password { get; set; }
}
private User _user = new User();
}
Next Steps
Explore more advanced topics like: