You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Blazor Server中结合Fluent Validation实现控件失焦即时验证

实现Blazor Server + Blazored.FluentValidation即时失去焦点验证

问题描述

我正在使用Blazor Server、Fluent Validation和Blazored.FluentValidation,之前用JQuery Validate + Fluent Validation时,离开文本框这类控件会立刻触发基础必填验证,但现在只有点击提交按钮,或输入无效值(比如年龄填199)时才会显示验证提示。进入空文本框再切换出去,完全没有反应,想实现空框失去焦点时显示必填提示。

解决方案

Blazor默认的输入组件仅在值发生变更时触发验证,初始为空的字段第一次失去焦点时,值没有变化(还是空),所以不会自动触发验证。要实现失去焦点即验证,需要手动触发字段级验证,以下是两种可行方案:

方案一:直接在输入组件添加失去焦点事件触发验证

在每个需要即时验证的输入组件上绑定@onfocusout事件,手动调用EditContext的字段验证方法:

修改后的表单代码片段:

<EditForm Model="@_person" OnValidSubmit="@SubmitValidForm" @ref="_editForm">
    <FluentValidationValidator DisableAssemblyScanning="@true" />
    <ValidationSummary />

    <p>
        <label>First Name: </label>
        <InputText @bind-Value="@_person.FirstName" 
                   @onfocusout="() => ValidateField(() => _person.FirstName)" />
        <ValidationMessage For="@(() => _person.FirstName)" />
    </p>

    <p>
        <label>Last Name: </label>
        <InputText @bind-Value="@_person.LastName" 
                   @onfocusout="() => ValidateField(() => _person.LastName)" />
        <ValidationMessage For="@(() => _person.LastName)" />
    </p>

    <!-- 其他字段按相同逻辑处理 -->

    <button type="submit">Save</button>
</EditForm>

@code {
    private readonly Person _person = new();
    private EditForm? _editForm;

    private void SubmitValidForm() 
        => Console.WriteLine("Form Submitted Successfully!");

    private void ValidateField<T>(Expression<Func<T>> fieldExpression)
    {
        if (_editForm?.EditContext == null) return;
        var fieldIdentifier = FieldIdentifier.Create(fieldExpression);
        _editForm.EditContext.ValidateField(fieldIdentifier);
    }
}

方案二:封装自定义输入组件(推荐,避免重复代码)

如果多个页面都需要该功能,建议封装自定义输入组件,把失去焦点触发验证的逻辑内置:

创建InputTextWithFocusValidation.razor:

@inherits InputText

<input @attributes="AdditionalAttributes" 
       class="@CssClass" 
       value="@CurrentValueAsString"
       @oninput="EventCallback.Factory.CreateBinder<string>(this, __value => CurrentValueAsString = __value, CurrentValueAsString)"
       @onfocusout="OnFocusOut" />

@code {
    [CascadingParameter]
    private EditContext? EditContext { get; set; }

    private void OnFocusOut()
    {
        if (EditContext == null) return;
        var fieldIdentifier = new FieldIdentifier(EditContext.Model, FieldIdentifier.FieldName);
        EditContext.ValidateField(fieldIdentifier);
    }
}

使用时直接替换原InputText:

<InputTextWithFocusValidation @bind-Value="@_person.FirstName" />
<ValidationMessage For="@(() => _person.FirstName)" />

注意事项

  • 对于异步验证规则(比如示例中的邮箱唯一性检查),频繁触发失去焦点会导致多次请求,建议添加防抖逻辑(比如延迟300ms再触发验证)
  • 如果需要针对所有字段统一开启该行为,可以通过自定义EditContext的扩展方法或全局组件拦截来实现

内容的提问来源于stack exchange,提问作者chobo2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:04:59