Mudblazor Select 具有多选和 Fluentvalidation For-Expression
Mudblazor Select with multiselect and Fluentvalidation For-Expression
我在 multiselect 模式下绑定到一个 select 字段,我 运行 遇到 [=31= 的“For”属性 的问题] 字段"。
使用 select 字段时,必须设置选项类型,在本例中为 string。为了使验证工作,需要设置“For”-属性 并指向与 select 字段选项相同类型的有效 属性(那是 string )。
但我期待一个 multiselect,所以我在我的模型中绑定到一个 IEnumerable ,并且还为此 属性 设置了验证码。
我没有必要的 属性 绑定,即使我有,验证也不会按预期工作。
我该如何进行这项工作?我尝试构建一个指向数组第一个元素的自定义表达式,但我不擅长表达,无法让它发挥作用。
@using FluentValidation
<MudCard>
<MudForm Model="@model" @ref="@form" Validation="@(testValidator.ValidateValue)" ValidationDelay="0">
<MudCardContent>
<MudSelect T="string" Label="Name"
HelperText="Pick your favorite name" MultiSelection="false" @bind-Value="model.Name" For="() => model.Name">
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
<MudSelect T="string" Label="Names"
HelperText="Pick your favorite names" MultiSelection="true" @bind-SelectedValues="model.Names"
@* For="() => model.Names" This needs to be set to make validation work *@
>
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
</MudCardContent>
</MudForm>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@(async () => await Submit())">Order</MudButton>
</MudCardActions>
</MudCard>
@code {
[Inject] ISnackbar Snackbar { get; set; }
private string[] _names = new string[] {
"Toni", "Matthew", "David"
};
MudForm form;
TestModelFluentValidator testValidator = new TestModelFluentValidator();
TestModel model = new TestModel();
public class TestModel
{
public string Name { get; set; }
public IEnumerable<string> Names { get; set; }
}
private async Task Submit()
{
await form.Validate();
if (form.IsValid)
{
Snackbar.Add("Submited!");
}
}
/// <summary>
/// A standard AbstractValidator which contains multiple rules and can be shared with the back end API
/// </summary>
/// <typeparam name="OrderModel"></typeparam>
public class TestModelFluentValidator : AbstractValidator<TestModel>
{
public TestModelFluentValidator()
{
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Names).Must((parent, property) => property.Contains("Toni"))
.WithMessage("Toni not found in those names!");
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<TestModel>.CreateWithOptions((TestModel)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
}
编辑:添加了代码示例并删除了不必要的代码。
好的,所以您可以通过引入虚拟 属性 并将 multi-select 组件绑定到它然后在验证期间测试其名称来欺骗该组件。
当表单组件将虚拟 属性 名称传递给验证方法时,您将传递的虚拟名称更改为您的集合名称,以便在流畅验证开始时匹配。
像这样:
@using FluentValidation
@using System.Reflection
<MudCard>
<MudForm Model="@model" @ref="@form" Validation="@(testValidator.ValidateValue)" ValidationDelay="0">
<MudCardContent>
<MudSelect T="string" Label="Name"
HelperText="Pick your favorite name" MultiSelection="false" @bind-Value="model.Name" For="() => model.Name">
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
<MudSelect T="string" Label="Names"
HelperText="Pick your favorite names" MultiSelection="true" @bind-Value="model.NameCollection" @bind-SelectedValues="model.Names"
For="@(() => model.NameCollection)"
>
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
</MudCardContent>
</MudForm>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@(async () => await Submit())">Order</MudButton>
</MudCardActions>
</MudCard>
@code {
[Inject] ISnackbar Snackbar { get; set; }
private string[] _names = new string[] {
"Toni", "Matthew", "David"
};
MudForm form;
TestModelFluentValidator testValidator = new TestModelFluentValidator();
TestModel model = new TestModel();
public class TestModel
{
public string Name { get; set; }
public string NameCollection { get; set; }
public IEnumerable<string> Names { get; set; }
}
private async Task Submit()
{
await form.Validate();
if (form.IsValid)
{
Snackbar.Add("Submited!");
}
}
/// <summary>
/// A standard AbstractValidator which contains multiple rules and can be shared with the back end API
/// </summary>
/// <typeparam name="OrderModel"></typeparam>
public class TestModelFluentValidator : AbstractValidator<TestModel>
{
public TestModelFluentValidator()
{
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Names).Must((parent, property) => property.Contains("Toni"))
.WithMessage("Toni not found in those names!");
}
private async Task<bool> IsUniqueAsync(string email)
{
// Simulates a long running http call
await Task.Delay(2000);
return email.ToLower() != "test@test.com";
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
propertyName = propertyName == nameof(TestModel.NameCollection) ? nameof(TestModel.Names) : propertyName;
var result = await ValidateAsync(ValidationContext<TestModel>.CreateWithOptions((TestModel)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
}
我在 multiselect 模式下绑定到一个 select 字段,我 运行 遇到 [=31= 的“For”属性 的问题] 字段"。
使用 select 字段时,必须设置选项类型,在本例中为 string。为了使验证工作,需要设置“For”-属性 并指向与 select 字段选项相同类型的有效 属性(那是 string )。
但我期待一个 multiselect,所以我在我的模型中绑定到一个 IEnumerable
我该如何进行这项工作?我尝试构建一个指向数组第一个元素的自定义表达式,但我不擅长表达,无法让它发挥作用。
@using FluentValidation
<MudCard>
<MudForm Model="@model" @ref="@form" Validation="@(testValidator.ValidateValue)" ValidationDelay="0">
<MudCardContent>
<MudSelect T="string" Label="Name"
HelperText="Pick your favorite name" MultiSelection="false" @bind-Value="model.Name" For="() => model.Name">
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
<MudSelect T="string" Label="Names"
HelperText="Pick your favorite names" MultiSelection="true" @bind-SelectedValues="model.Names"
@* For="() => model.Names" This needs to be set to make validation work *@
>
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
</MudCardContent>
</MudForm>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@(async () => await Submit())">Order</MudButton>
</MudCardActions>
</MudCard>
@code {
[Inject] ISnackbar Snackbar { get; set; }
private string[] _names = new string[] {
"Toni", "Matthew", "David"
};
MudForm form;
TestModelFluentValidator testValidator = new TestModelFluentValidator();
TestModel model = new TestModel();
public class TestModel
{
public string Name { get; set; }
public IEnumerable<string> Names { get; set; }
}
private async Task Submit()
{
await form.Validate();
if (form.IsValid)
{
Snackbar.Add("Submited!");
}
}
/// <summary>
/// A standard AbstractValidator which contains multiple rules and can be shared with the back end API
/// </summary>
/// <typeparam name="OrderModel"></typeparam>
public class TestModelFluentValidator : AbstractValidator<TestModel>
{
public TestModelFluentValidator()
{
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Names).Must((parent, property) => property.Contains("Toni"))
.WithMessage("Toni not found in those names!");
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<TestModel>.CreateWithOptions((TestModel)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
}
编辑:添加了代码示例并删除了不必要的代码。
好的,所以您可以通过引入虚拟 属性 并将 multi-select 组件绑定到它然后在验证期间测试其名称来欺骗该组件。
当表单组件将虚拟 属性 名称传递给验证方法时,您将传递的虚拟名称更改为您的集合名称,以便在流畅验证开始时匹配。
像这样:
@using FluentValidation
@using System.Reflection
<MudCard>
<MudForm Model="@model" @ref="@form" Validation="@(testValidator.ValidateValue)" ValidationDelay="0">
<MudCardContent>
<MudSelect T="string" Label="Name"
HelperText="Pick your favorite name" MultiSelection="false" @bind-Value="model.Name" For="() => model.Name">
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
<MudSelect T="string" Label="Names"
HelperText="Pick your favorite names" MultiSelection="true" @bind-Value="model.NameCollection" @bind-SelectedValues="model.Names"
For="@(() => model.NameCollection)"
>
@foreach (var name in _names)
{
<MudSelectItem T="string" Value="@name">@name</MudSelectItem>
}
</MudSelect>
</MudCardContent>
</MudForm>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@(async () => await Submit())">Order</MudButton>
</MudCardActions>
</MudCard>
@code {
[Inject] ISnackbar Snackbar { get; set; }
private string[] _names = new string[] {
"Toni", "Matthew", "David"
};
MudForm form;
TestModelFluentValidator testValidator = new TestModelFluentValidator();
TestModel model = new TestModel();
public class TestModel
{
public string Name { get; set; }
public string NameCollection { get; set; }
public IEnumerable<string> Names { get; set; }
}
private async Task Submit()
{
await form.Validate();
if (form.IsValid)
{
Snackbar.Add("Submited!");
}
}
/// <summary>
/// A standard AbstractValidator which contains multiple rules and can be shared with the back end API
/// </summary>
/// <typeparam name="OrderModel"></typeparam>
public class TestModelFluentValidator : AbstractValidator<TestModel>
{
public TestModelFluentValidator()
{
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Names).Must((parent, property) => property.Contains("Toni"))
.WithMessage("Toni not found in those names!");
}
private async Task<bool> IsUniqueAsync(string email)
{
// Simulates a long running http call
await Task.Delay(2000);
return email.ToLower() != "test@test.com";
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
propertyName = propertyName == nameof(TestModel.NameCollection) ? nameof(TestModel.Names) : propertyName;
var result = await ValidateAsync(ValidationContext<TestModel>.CreateWithOptions((TestModel)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
}