Exercise 6: Form with Validation Using EditForm and Data Annotations
Blazor Exercise 6: Form with Validation Using EditForm and Data Annotations
Awesome! You've built a solid foundation with Blazor components, communication, and data binding. Now, let’s dive into **form validation** in Blazor — a must-have feature for any robust business application. This exercise will guide you through creating a user registration form with built-in validation using Blazor's powerful EditForm and Data Annotations.
✅ Goal:
Build a user registration form with built-in validation using:
EditForm: The central component for Blazor forms.DataAnnotationsValidator: To enable attribute-based validation.ValidationSummary&ValidationMessage: To display validation errors.- Blazor's built-in input components:
InputText,InputNumber,InputCheckbox.
๐งฉ Concepts Covered:
- **Model-based validation** using C# Data Annotations attributes (e.g.,
[Required],[StringLength],[EmailAddress],[Range]). - Understanding the **
EditFormlifecycle** and itsOnValidSubmitandOnInvalidSubmitevents. - How to use
DataAnnotationsValidatorto hook up your model's validation attributes. - Displaying a **summary of all validation errors** using
ValidationSummary. - Displaying **per-field validation errors** using
ValidationMessage. - Using Blazor's built-in
Input*components for seamless form integration.
๐ง Steps:
Step 1: Create a model class UserRegistration.cs
Create a new C# class file named UserRegistration.cs. It's good practice to place model classes in a dedicated Models folder in your project. This class will define the structure of the data for our registration form and include Data Annotation attributes for validation rules.
<!-- Models/UserRegistration.cs -->
using System.ComponentModel.DataAnnotations;
public class UserRegistration
{
[Required(ErrorMessage = "Name is required")]
[StringLength(50, ErrorMessage = "Name can't exceed 50 characters")]
public string Name { get; set; } = ""; // Initialize to prevent null reference warnings
[Required(ErrorMessage = "Email is required")]
[EmailAddress(ErrorMessage = "Invalid email format")]
public string Email { get; set; } = ""; // Initialize to prevent null reference warnings
[Range(18, 100, ErrorMessage = "Age must be between 18 and 100")]
public int Age { get; set; } // int defaults to 0, which is outside range for age < 18
[Required(ErrorMessage = "You must accept the terms")] // Required for boolean
public bool AcceptTerms { get; set; } = false; // Initialize to false
}
Explanation of Data Annotations:
[Required]: Ensures the field cannot be empty.[StringLength(50)]: Sets a maximum length for string fields.[EmailAddress]: Validates that the input is a valid email format.[Range(18, 100)]: Ensures a numerical value falls within a specified range.ErrorMessage: Customizes the validation message displayed to the user.
Step 2: Create a Razor page named Register.razor
Create a new Razor page file named Register.razor in your Pages folder. This page will contain the EditForm and all the input and validation components.
<!-- Pages/Register.razor -->
@page "/register"
@using System.ComponentModel.DataAnnotations <!-- Required for Data Annotations -->
@using YourAppName.Models <!-- Replace YourAppName with your actual project name if UserRegistration is in a separate Models folder -->
<h3 class="heading3">Register</h3>
<EditForm Model="@user" OnValidSubmit="HandleValidSubmit" OnInvalidSubmit="HandleInvalidSubmit">
<DataAnnotationsValidator /> <!-- Enables validation based on Data Annotations on the 'user' model -->
<ValidationSummary class="validation-summary" /> <!-- Displays all validation errors in a list -->
<div class="form-group">
<label for="nameInput">Name:</label>
<InputText id="nameInput" @bind-Value="user.Name" class="form-control" />
<ValidationMessage For="@(() => user.Name)" class="validation-message" /> <!-- Shows error for Name field -->
</div>
<div class="form-group">
<label for="emailInput">Email:</label>
<InputText id="emailInput" @bind-Value="user.Email" class="form-control" />
<ValidationMessage For="@(() => user.Email)" class="validation-message" /> <!-- Shows error for Email field -->
</div>
<div class="form-group">
<label for="ageInput">Age:</label>
<InputNumber id="ageInput" @bind-Value="user.Age" class="form-control" />
<ValidationMessage For="@(() => user.Age)" class="validation-message" /> <!-- Shows error for Age field -->
</div>
<div class="form-group">
<label>
<InputCheckbox @bind-Value="user.AcceptTerms" />
I accept the terms
</label>
<ValidationMessage For="@(() => user.AcceptTerms)" class="validation-message" /> <!-- Shows error for AcceptTerms -->
</div>
<button type="submit" class="blazor-button">Submit</button>
</EditForm>
@if (isSubmitted)
{
<p style="color:green; margin-top: 1rem;">✅ Registration Successful for @user.Name!</p>
}
@code {
// Create an instance of our UserRegistration model
UserRegistration user = new();
// Flag to indicate successful submission
bool isSubmitted = false;
// This method is called when the form is submitted AND all validation rules pass
void HandleValidSubmit()
{
isSubmitted = true; // Set flag to show success message
Console.WriteLine($"User Registered: Name: {user.Name}, Email: {user.Email}, Age: {user.Age}, Accepted Terms: {user.AcceptTerms}");
// Here you would typically send the 'user' data to a backend API or save it.
}
// This method is called when the form is submitted AND there are validation errors
void HandleInvalidSubmit()
{
isSubmitted = false; // Ensure success message is not shown
Console.WriteLine("Form submission failed due to validation errors.");
// You could add logging or more complex error handling here.
}
}
Key points in Register.razor:
<EditForm Model="@user" ...>: Binds the form to ourUserRegistrationmodel.OnValidSubmitandOnInvalidSubmitare crucial event handlers.<DataAnnotationsValidator />: This component is mandatory to make the Data Annotations onUserRegistrationeffective.<ValidationSummary />: Displays a list of all validation errors that are currently active in the form.<InputText />,<InputNumber />,<InputCheckbox />: Blazor's built-in input components that automatically integrate withEditFormand validation.<ValidationMessage For="@(() => user.Name)" />: Shows the error message for a specific field. The lambda expression@(() => user.Name)provides a strong-typed way to link the validation message to the property.HandleValidSubmit(): Executed only if the form data is valid according to the Data Annotations.HandleInvalidSubmit(): Executed if the form data is invalid.
๐งช Try this:
- Run your Blazor application.
- Navigate to
/register. - Try submitting the form with **empty values**. Observe the
[Required]validation messages. - Enter an **invalid email format** (e.g., "test"). Observe the
[EmailAddress]validation message. - Enter an **age less than 18** or greater than 100. Observe the
[Range]validation message. - Try submitting without checking "I accept the terms". Observe the
[Required]validation message for the boolean. - Finally, **fill all fields correctly** and click "Submit". Observe the success message and check your browser's console for the logged user details.
๐ฏ Expected Output:
You will see real-time validation feedback as you interact with the form.
- **Empty submission:** A summary list of all errors will appear at the top, and individual error messages will appear below each invalid field.
- **Invalid data:** Specific error messages (e.g., "Invalid email format", "Age must be between 18 and 100") will appear.
- **Successful submission:** The validation messages will disappear, and a green success message "✅ Registration Successful for [Your Name]!" will appear below the form.
๐ง Bonus Challenges:
- **Disable the Submit button:** Modify the "Submit" button to be disabled until the
AcceptTermscheckbox is checked. (Hint: Use thedisabledHTML attribute and bind it touser.AcceptTerms). - **Add Password & ConfirmPassword fields:**
- Add
PasswordandConfirmPasswordproperties to yourUserRegistrationmodel. - Use
[Required]and[StringLength]on the password. - Implement **custom validation** to ensure
PasswordandConfirmPasswordmatch. (Hint: This might involve implementingIValidatableObjecton yourUserRegistrationmodel or creating a custom validation attribute).
- Add
- **Explore
@bindalternatives:** For theInputTextfields, try replacing@bind-Value="user.Name"withValue="@user.Name" ValueExpression="@(() => user.Name)" OnChange="@((args) => user.Name = args.Value.ToString())". This gives you finer control over when the value is updated and how.
✅ You’ve now implemented a full Blazor validation flow! This is a critical skill for building robust and user-friendly Blazor applications.
Comments
Post a Comment