我正在学习Blazor(使用MudBlazor)和FluentValidation。主要参考MudBlazor文档中的模式和实践。我有一个顶级表单(主表单),其中包含一些基本输入字段和一些由API驱动的选择列表。我将选择列表转换为组件,因为我将在应用程序的其他地方重复使用它们。
我已经成功地将FluentValidation添加到了主表单中,并在保存时看到字段变为红色并显示错误消息。但是,我无法弄清楚如何验证并在嵌套/子组件中显示控件上的错误。我知道这是由于我的经验不足,但我在互联网上没有找到太多关于这种特定情况的信息。
接下来是代码。以下是我的问题示例的一小部分代码。可以在Try MudBlazor中找到一个工作示例。
编辑:如果这是一种不好的组件模式,那我没关系。请告诉我,我会放弃这种方法。
MainForm.razor
<MudForm Model="@formData" @ref="@form" Validation="@(modelValidator.ValidateValue)">
<MudGrid>
<MudItem xs=12>
<MudTextField @bind-Value="formData.LastName" Label="Last Name" For="(() => formData.LastName)"
Variant="Variant.Text" MaxLength="50"></MudTextField>
</MudItem>
<MudItem xs=12>
<MudTextField @bind-Value="formData.FirstName" Label="First Name" For="(() => formData.FirstName)"
Variant="Variant.Text" MaxLength="50"></MudTextField>
</MudItem>
<MudItem xs=12>
<RaceSelector @bind-SelectedRaceId="@selectedRaceId" />
</MudItem>
<MudItem xs=12>
<span>The Selected Race ID is: @selectedRaceId</span>
</MudItem>
<MudItem xs=12>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="async () => await Submit() ">Save</MudButton>
</MudItem>
</MudGrid>
</MudForm>
@code {
private Model formData = new();
private string selectedRaceId = string.Empty;
private ModelValidator modelValidator = new();
private MudForm form;
private async Task Submit()
{
await form.Validate();
if (form.IsValid)
{
// Post to API
}
}
}
RaceSelector.razor
<MudSelect @bind-Value="SelectedRaceId" Placeholder="" T="string"
Label="Race" Variant="Variant.Outlined">
@foreach (var race in RaceList)
{
<MudSelectItem T="string" Value="@race.Id.ToString()">@race.Name</MudSelectItem>
}
</MudSelect>
@code {
private List<Race>? RaceList { get; set; }
private string selectedRaceId;
[Parameter]
public string SelectedRaceId
{
get
{
return selectedRaceId;
}
set
{
// Wire-up two way binding
if (selectedRaceId != value)
{
selectedRaceId = value;
if (SelectedRaceIdChanged.HasDelegate)
{
SelectedRaceIdChanged.InvokeAsync(value);
}
}
}
}
[Parameter]
public EventCallback<string> SelectedRaceIdChanged { get; set; }
protected override async Task OnInitializedAsync()
{
// Pretend this is a call to the API
RaceList = new List<Race>
{
new Race(1, "American Ind/Alaskan"),
new Race(2, "Asian or Pacific Isl"),
new Race(3, "Black, not Hispanic"),
new Race(4, "Hispanic"),
new Race(5, "White, not Hispanic"),
new Race(6, "Other"),
new Race(7, "Multi-Racial"),
new Race(8, "Unknown")
};
}
}
Model.cs 和 Race.cs
public class Model
{
public string FirstName {get; set;}
public string LastName {get; set;}
public string RaceId {get; set;}
}
public class Race
{
public Race() {}
public Race(int id, string name)
{
Id = id;
Name = name;
}
public int Id {get; set;}
public string Name {get; set;}
}
ModelValidator.cs
using FluentValidation;
public class ModelValidator : AbstractValidator<Model>
{
public ModelValidator()
{
RuleFor(x => x.LastName)
.NotEmpty();
RuleFor(x => x.FirstName)
.NotEmpty();
RuleFor(x => x.RaceId)
.NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<Model>.CreateWithOptions((Model)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}