Form Validation Examples

Basic Form Validation #

Example of form validation using EditForm and DataAnnotations with real-time validation feedback.

<EditForm Model="@model" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <div class="flex max-w-md flex-col gap-4">
        <div>
            <div class="mb-2 block">
                <Label For="email" Value="Email address" />
            </div>
            <TextInput TValue="string" Id="email" @@bind-Value="model.Email" Type="email" />
            <ValidationMessage For="@(() => model.Email)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="password" Value="Password" />
            </div>
            <TextInput TValue="string" Id="password" @@bind-Value="model.Password" Type="password" />
            <ValidationMessage For="@(() => model.Password)" />
        </div>
        <Button Type="submit">Register</Button>
    </div>
</EditForm>

Custom Validation #

Example of custom validation rules with field-level validation and custom messages.

<EditForm Model="@customModel" OnValidSubmit="@HandleCustomValidSubmit">
    <CustomValidator @ref="customValidator" />
    <div class="flex max-w-md flex-col gap-4">
        <div>
            <div class="mb-2 block">
                <Label For="username" Value="Username" />
            </div>
            <TextInput TValue="string" Id="username" @@bind-Value="customModel.Username" />
            <ValidationMessage For="@(() => customModel.Username)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="confirmUsername" Value="Confirm Username" />
            </div>
            <TextInput TValue="string" Id="confirmUsername" @@bind-Value="customModel.ConfirmUsername" />
            <ValidationMessage For="@(() => customModel.ConfirmUsername)" />
        </div>
        <Button Type="submit">Submit</Button>
    </div>
</EditForm>

Form State Management #

Example showing form state management including dirty state tracking and reset functionality.

Form Status: Unmodified
<EditForm EditContext="@editContext" OnValidSubmit="@HandleStateFormSubmit">
    <DataAnnotationsValidator />
    <div class="flex max-w-md flex-col gap-4">
        <div>
            <div class="mb-2 block">
                <Label For="name" Value="Name" />
            </div>
            <TextInput TValue="string" Id="name" Value="@name" ValueChanged="@OnNameChanged" />
            <ValidationMessage For="@(() => stateModel.Name)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="age" Value="Age" />
            </div>
            <TextInput TValue="int" Id="age" Value="@age" ValueChanged="@OnAgeChanged" Type="number" />
            <ValidationMessage For="@(() => stateModel.Age)" />
        </div>
        <div class="flex gap-2">
            <Button Type="submit" Disabled="@(!editContext?.IsModified() ?? true)">Submit</Button>
            <Button Color="ButtonColor.Light" OnClick="@ResetForm">Reset</Button>
        </div>
        <div class="text-sm text-gray-500">
            Form Status: @(editContext?.IsModified() ?? false ? "Modified" : "Unmodified")
        </div>
    </div>
</EditForm>

Complex Form Example #

A complex form example with multiple field types and validation rules.

<EditForm Model="@complexModel" OnValidSubmit="@HandleComplexFormSubmit">
    <DataAnnotationsValidator />
    <div class="flex max-w-md flex-col gap-4">
        <div>
            <div class="mb-2 block">
                <Label For="fullName" Value="Full Name" />
            </div>
            <TextInput TValue="string" Id="fullName" @@bind-Value="complexModel.FullName" />
            <ValidationMessage For="@(() => complexModel.FullName)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="email" Value="Email" />
            </div>
            <TextInput TValue="string" Id="email" @@bind-Value="complexModel.Email" Type="email" />
            <ValidationMessage For="@(() => complexModel.Email)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="age" Value="Age" />
            </div>
            <TextInput TValue="int" Id="age" @@bind-Value="complexModel.Age" Type="number" />
            <ValidationMessage For="@(() => complexModel.Age)" />
        </div>
        <div>
            <div class="mb-2 block">
                <Label For="country" Value="Country" />
            </div>
            <Select Id="country" @bind-Value="complexModel.Country">
                <option value="">Select a country</option>
                <option value="US">United States</option>
                <option value="UK">United Kingdom</option>
                <option value="CA">Canada</option>
            </Select>
            <ValidationMessage For="@(() => complexModel.Country)" />
        </div>
        <div class="flex items-center gap-2">
            <Checkbox Id="terms" @bind-Value="complexModel.AcceptTerms" />
            <Label For="terms">I accept the terms and conditions</Label>
        </div>
        <ValidationMessage For="@(() => complexModel.AcceptTerms)" />
        <Button Type="submit" Disabled="@isSubmitting">
            @if (isSubmitting)
            {
                <Spinner class="mr-2" />
                <span>Submitting...</span>
            }
            else
            {
                <span>Submit</span>
            }
        </Button>
    </div>
</EditForm>
An unhandled error has occurred. Reload 🗙