如何在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
相关产品推荐
相关产品推荐

