将 EditForm 绑定到数组时如何使 EditContext.Validate() 起作用
How to get EditContext.Validate() to work when binding EditForm to an array
我创建了一个 EditForm
包装一个 table 像这样:
**Index.razor**
@using System.ComponentModel.DataAnnotations;
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
<DataAnnotationsValidator></DataAnnotationsValidator>
<table class="table">
<thead>
<tr>
<th>Code</th>
</tr>
</thead>
<tbody>
@foreach (var vm in vms)
{
<tr>
<td>
<InputText @bind-Value="vm.Code"></InputText>
<ValidationMessage For="@(() => vm.Code)"></ValidationMessage>
</td>
</tr>
}
</tbody>
</table>
<input type="submit" class="btn btn-primary" value="Submit" />
</EditForm>
@code{
List<MyClass> vms;
EditForm Form;
class MyClass
{
[Required(ErrorMessage ="Required")]
public string Code { get; set; }
}
protected override void OnInitialized()
{
vms = new List<MyClass>()
{
new MyClass()
{
Code = "1111"
},
new MyClass()
{
Code = "2222"
}
};
}
private void Submit()
{
bool IsValid = Form.EditContext.Validate();
}
}
按照下图正确弹出消息错误:
但是,当我提交表单然后验证时,它似乎并没有选择无效状态。
调用EditContext.Validate()
后仍然返回true,虽然有错误
如何让它工作? (当 EditForm 上下文中的至少一个模型项无效时,我如何得到 false,以便我可以进行其他验证?)
[2021-01-16 更新]
也可以在这里找到答案。
https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/
简而言之,内置的 DataAnnotationValidation 不适用于数组。
要使其正常工作,您必须
- installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
- 将数组设为属性,然后用[ValidateComplexType]修饰它
- 使用 ObjectGraphDataAnnotationsValidator
首先,我建议你这样做
<EditForm EditContext="editContext" OnSubmit="Submit">
而不是
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
这需要您像这样定义 EditContext:EditContext editContext;
并在 OnInitialized 方法中实例化 EditContext 对象,如下所示:
protected override void OnInitialized()
{
vms = new List<MyClass>() { new MyClass() { Code = "1111" },
new MyClass() { Code = "2222" }
};
editContext = new EditContext(vms);
}
顺便说一下,为什么使用 OnSubmit
而不是 OnValidSubmit
和 OnInvalidSubmit
?您在寻找挑战吗?
EditContext.Validate() returns incorrect results
这不是真的...
问题是您尝试绑定到 MyClass 的数组...但是您应该绑定到单个对象。绑定到一个数组是可能的,但我不能扩展它,因为它值得一个新问题。只要说您可以绑定的对象数组本身必须是单个有界对象的字段 (属性) 就够了,例如,包含他说的语言列表的 Student 对象。
为了验证以上内容,更改List<MyClass> vms;
进入MyClass model = new MyClass();
和editContext = new EditContext(vms);
进入editContext = new EditContext(model);
而不是
@foreach (var vm in vms)
{
<tr>
<td>
<InputText @bind-Value="vm.Code"></InputText>
<ValidationMessage For="@(() => vm.Code)">
</ValidationMessage>
</td>
</tr>
}
代码如下:
<tr>
<td>
<InputText @bind-Value="model.Code"></InputText>
<ValidationMessage For="@(() => model.Code)"></ValidationMessage>
</td>
</tr>
现在,运行你的代码,验证EditContext.Validate()
的诽谤是否正当。
更新
以下代码示例描述了如何绑定到 EditForm 中的集合,以及如何验证该集合以及模型中的其他字段(该集合是该模型的字段成员)。
注意:您应该在包管理器控制台中执行 Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4
,以访问使示例工作所需的对象...
@page "/"
@using Microsoft.AspNetCore.Components.Forms
@using System.ComponentModel.DataAnnotations;
<EditForm EditContext="EditContext" OnSubmit="@OnSubmitHandler">
@*<DataAnnotationsValidator />*@
<ObjectGraphDataAnnotationsValidator/>
<p>
<label for="name">Enter name: </label>
<InputText id="name" @bind-Value="customer.Name" /><br />
<ValidationMessage For="@(() => customer.Name)" />
</p>
@foreach (var phone in customer.phones)
{
<p>
<label>Enter phone: </label>
<InputText @bind-Value="phone.PhoneNumber" />
<ValidationMessage For="@(() => phone.PhoneNumber)" />
</p>
}
<p>
<button type="submit">submit</button>
</p>
</EditForm>
<div>
<p>Edit customer</p>
<p>@customer.Name</p>
@foreach (var phone in customer.phones)
{
<p>@phone.PhoneNumber</p>
}
</div>
<div>
<p>Is model validated: @validated.ToString()</p>
</div>
@code {
EditContext EditContext;
Customer customer;
bool validated;
protected override void OnInitialized()
{
customer = new Customer();
EditContext = new EditContext(customer);
}
private void OnSubmitHandler()
{
validated = EditContext.Validate();
}
public class Customer
{
[Required]
public string Name { get; set; }
[ValidateComplexType]
public List<Phone> phones { get; set; } = new List<Phone>() { new Phone { }, new Phone { }, new Phone { }};
}
public class Phone
{
[Required]
public string PhoneNumber { get; set; }
}
}
我创建了一个 EditForm
包装一个 table 像这样:
**Index.razor**
@using System.ComponentModel.DataAnnotations;
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
<DataAnnotationsValidator></DataAnnotationsValidator>
<table class="table">
<thead>
<tr>
<th>Code</th>
</tr>
</thead>
<tbody>
@foreach (var vm in vms)
{
<tr>
<td>
<InputText @bind-Value="vm.Code"></InputText>
<ValidationMessage For="@(() => vm.Code)"></ValidationMessage>
</td>
</tr>
}
</tbody>
</table>
<input type="submit" class="btn btn-primary" value="Submit" />
</EditForm>
@code{
List<MyClass> vms;
EditForm Form;
class MyClass
{
[Required(ErrorMessage ="Required")]
public string Code { get; set; }
}
protected override void OnInitialized()
{
vms = new List<MyClass>()
{
new MyClass()
{
Code = "1111"
},
new MyClass()
{
Code = "2222"
}
};
}
private void Submit()
{
bool IsValid = Form.EditContext.Validate();
}
}
按照下图正确弹出消息错误:
但是,当我提交表单然后验证时,它似乎并没有选择无效状态。
调用EditContext.Validate()
后仍然返回true,虽然有错误
如何让它工作? (当 EditForm 上下文中的至少一个模型项无效时,我如何得到 false,以便我可以进行其他验证?)
[2021-01-16 更新] 也可以在这里找到答案。 https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/
简而言之,内置的 DataAnnotationValidation 不适用于数组。 要使其正常工作,您必须
- installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
- 将数组设为属性,然后用[ValidateComplexType]修饰它
- 使用 ObjectGraphDataAnnotationsValidator
首先,我建议你这样做
<EditForm EditContext="editContext" OnSubmit="Submit">
而不是
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
这需要您像这样定义 EditContext:EditContext editContext;
并在 OnInitialized 方法中实例化 EditContext 对象,如下所示:
protected override void OnInitialized()
{
vms = new List<MyClass>() { new MyClass() { Code = "1111" },
new MyClass() { Code = "2222" }
};
editContext = new EditContext(vms);
}
顺便说一下,为什么使用 OnSubmit
而不是 OnValidSubmit
和 OnInvalidSubmit
?您在寻找挑战吗?
EditContext.Validate() returns incorrect results
这不是真的...
问题是您尝试绑定到 MyClass 的数组...但是您应该绑定到单个对象。绑定到一个数组是可能的,但我不能扩展它,因为它值得一个新问题。只要说您可以绑定的对象数组本身必须是单个有界对象的字段 (属性) 就够了,例如,包含他说的语言列表的 Student 对象。
为了验证以上内容,更改List<MyClass> vms;
进入MyClass model = new MyClass();
和editContext = new EditContext(vms);
进入editContext = new EditContext(model);
而不是
@foreach (var vm in vms)
{
<tr>
<td>
<InputText @bind-Value="vm.Code"></InputText>
<ValidationMessage For="@(() => vm.Code)">
</ValidationMessage>
</td>
</tr>
}
代码如下:
<tr>
<td>
<InputText @bind-Value="model.Code"></InputText>
<ValidationMessage For="@(() => model.Code)"></ValidationMessage>
</td>
</tr>
现在,运行你的代码,验证EditContext.Validate()
的诽谤是否正当。
更新
以下代码示例描述了如何绑定到 EditForm 中的集合,以及如何验证该集合以及模型中的其他字段(该集合是该模型的字段成员)。
注意:您应该在包管理器控制台中执行 Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4
,以访问使示例工作所需的对象...
@page "/"
@using Microsoft.AspNetCore.Components.Forms
@using System.ComponentModel.DataAnnotations;
<EditForm EditContext="EditContext" OnSubmit="@OnSubmitHandler">
@*<DataAnnotationsValidator />*@
<ObjectGraphDataAnnotationsValidator/>
<p>
<label for="name">Enter name: </label>
<InputText id="name" @bind-Value="customer.Name" /><br />
<ValidationMessage For="@(() => customer.Name)" />
</p>
@foreach (var phone in customer.phones)
{
<p>
<label>Enter phone: </label>
<InputText @bind-Value="phone.PhoneNumber" />
<ValidationMessage For="@(() => phone.PhoneNumber)" />
</p>
}
<p>
<button type="submit">submit</button>
</p>
</EditForm>
<div>
<p>Edit customer</p>
<p>@customer.Name</p>
@foreach (var phone in customer.phones)
{
<p>@phone.PhoneNumber</p>
}
</div>
<div>
<p>Is model validated: @validated.ToString()</p>
</div>
@code {
EditContext EditContext;
Customer customer;
bool validated;
protected override void OnInitialized()
{
customer = new Customer();
EditContext = new EditContext(customer);
}
private void OnSubmitHandler()
{
validated = EditContext.Validate();
}
public class Customer
{
[Required]
public string Name { get; set; }
[ValidateComplexType]
public List<Phone> phones { get; set; } = new List<Phone>() { new Phone { }, new Phone { }, new Phone { }};
}
public class Phone
{
[Required]
public string PhoneNumber { get; set; }
}
}