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

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:

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:

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:

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.

Best Practice: Use Blazor's built-in components like <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: