Blazor Wasm/Server中不使用EditForm的表单验证方案求助
Blazor 原生/轻量实现带验证的多选下拉框与富文本编辑器
一、原生集成验证的多选下拉框
基于Blazor内置的InputBase<T>自定义组件,天然兼容EditForm的DataAnnotations验证,无需依赖第三方库。如果需要样式美化,可添加轻量JS做UI交互(不影响数据绑定与验证逻辑)。
自定义多选组件代码(MultiSelect.razor)
@typeparam TValue @inherits InputBase<List<TValue>> <div class="multi-select"> <label>@Label</label> @foreach (var option in Options) { <div class="option-item"> <input type="checkbox" id="option-@option.GetHashCode()" checked="@CurrentValue.Contains(option)" @onchange="(e) => ToggleSelection(option, e.Value)" /> <label for="option-@option.GetHashCode()">@(OptionLabelFunc?.Invoke(option) ?? option.ToString())</label> </div> } <ValidationMessage For="@ValueExpression" /> </div> @code { [Parameter] public string Label { get; set; } [Parameter] public IEnumerable<TValue> Options { get; set; } = Enumerable.Empty<TValue>(); [Parameter] public Func<TValue, string> OptionLabelFunc { get; set; } private void ToggleSelection(TValue option, object isChecked) { var newValue = new List<TValue>(CurrentValue); if ((bool)isChecked) { if (!newValue.Contains(option)) newValue.Add(option); } else { newValue.Remove(option); } CurrentValue = newValue; } protected override bool TryParseValueFromString(string value, out List<TValue> result, out string validationErrorMessage) { // 直接通过checkbox绑定数据,此方法不会触发,返回默认值即可 result = CurrentValue; validationErrorMessage = null; return true; } }
使用示例(集成EditForm与验证)
<EditForm Model="@userModel" OnValidSubmit="@HandleSubmit"> <DataAnnotationsValidator /> <ValidationSummary /> <MultiSelect Label="选择兴趣爱好" Options="@hobbyOptions" @bind-Value="@userModel.SelectedHobbies" /> <button type="submit">提交</button> </EditForm> @code { private List<string> hobbyOptions = new() { "阅读", "运动", "编程", "旅行" }; private UserModel userModel = new(); private void HandleSubmit() { // 处理表单提交逻辑 } public class UserModel { [Required(ErrorMessage = "请至少选择一个兴趣爱好")] [MinLength(1, ErrorMessage = "请至少选择一个兴趣爱好")] public List<string> SelectedHobbies { get; set; } = new(); } }
二、集成EditForm验证的富文本编辑器(以Summernote为例)
通过封装InputBase<string>组件,结合IJSRuntime与JS编辑器交互,同时保留Blazor的验证机制,无需依赖第三方UI库。
自定义富文本编辑器组件(SummernoteEditor.razor)
@inherits InputBase<string> @inject IJSRuntime JSRuntime <div class="summernote-container"> <label>@Label</label> <div @ref="@editorRef" class="summernote"></div> <ValidationMessage For="@ValueExpression" /> </div> @code { [Parameter] public string Label { get; set; } private ElementReference editorRef; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // 初始化Summernote并绑定回调 await JSRuntime.InvokeVoidAsync("initSummernote", editorRef, CurrentValue, DotNetObjectReference.Create(this)); } else if (CurrentValue != await JSRuntime.InvokeAsync<string>("getSummernoteContent", editorRef)) { // 同步Blazor模型值到编辑器 await JSRuntime.InvokeVoidAsync("setSummernoteContent", editorRef, CurrentValue); } } [JSInvokable] public void OnContentChanged(string content) { // 编辑器内容变化时更新Blazor绑定值 CurrentValueAsString = content; } protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) { result = value; validationErrorMessage = null; return true; } }
配套JS代码(wwwroot/js/summernote.js)
function initSummernote(element, initialContent, dotNetRef) { $(element).summernote({ height: 200, callbacks: { onChange: function(contents) { dotNetRef.invokeMethodAsync('OnContentChanged', contents); } } }); $(element).summernote('code', initialContent); } function getSummernoteContent(element) { return $(element).summernote('code'); } function setSummernoteContent(element, content) { $(element).summernote('code', content); }
使用示例(集成EditForm与验证)
<EditForm Model="@postModel" OnValidSubmit="@HandlePublish"> <DataAnnotationsValidator /> <ValidationSummary /> <SummernoteEditor Label="文章内容" @bind-Value="@postModel.Content" /> <button type="submit">发布文章</button> </EditForm> @code { private PostModel postModel = new(); private void HandlePublish() { // 处理文章发布逻辑 } public class PostModel { [Required(ErrorMessage = "请填写文章内容")] [MinLength(10, ErrorMessage = "内容长度不能少于10个字符")] public string Content { get; set; } } }
核心思路总结
所有自定义控件通过继承InputBase<T>实现,这是Blazor原生集成EditForm验证系统的标准方式:
- 组件自动继承验证状态管理,无需手动处理验证触发与错误展示
- 数据双向绑定逻辑通过
CurrentValue/CurrentValueAsString统一处理 - JS仅负责UI交互或编辑器初始化,核心数据与验证逻辑由Blazor控制
内容的提问来源于stack exchange,提问作者Ramin Azali
相关产品推荐
相关产品推荐

