问题
I created an EditForm
wrapping a table like so:
**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();
}
}
The message error pops correctly as per the below image:
However, when I submit the form and then validate, it does not seem to pick up the invalid state.
It is still returning true after calling EditContext.Validate()
, even though there are errors.
How do I get this to work? (How do I get false when at least one of the model item in the EditForm context is invalid so I can do my other validation stuff?)
[Updated 2021-01-16] Answers can also be found here. https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/
In short, the built-in DataAnnotationValidation does not work with arrays. To get it working, you must
- installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
- Make the array an attribute and then decorate it with [ValidateComplexType]
- Use ObjectGraphDataAnnotationsValidator
回答1:
First off, I'd suggest you do something like this
<EditForm EditContext="editContext" OnSubmit="Submit">
Instead of
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
Which requires you to define EditContext like this: EditContext editContext;
And instantiate the EditContext object in the OnInitialized method like this:
protected override void OnInitialized()
{
vms = new List<MyClass>() { new MyClass() { Code = "1111" },
new MyClass() { Code = "2222" }
};
editContext = new EditContext(vms);
}
Incidentally, why do you use OnSubmit
instead of OnValidSubmit
and OnInvalidSubmit
? Are you looking for challenges ?
EditContext.Validate() returns incorrect results
That is not true...
The issue is that you try to bind to an array of MyClass...But you should bind to a single object. Binding to an array is possible, but I can't extend on it as it merits a new question. Suffice it to say that the array of objects you can bind to must be itself a field (property) of an a single bounded object, as for instance, a Student object that contains a list of Languages he speaks.
In order to verify the above, change List<MyClass> vms;
into MyClass model = new MyClass();
and editContext = new EditContext(vms);
into editContext = new EditContext(model);
and instead of
@foreach (var vm in vms)
{
<tr>
<td>
<InputText @bind-Value="vm.Code"></InputText>
<ValidationMessage For="@(() => vm.Code)">
</ValidationMessage>
</td>
</tr>
}
code this:
<tr>
<td>
<InputText @bind-Value="model.Code"></InputText>
<ValidationMessage For="@(() => model.Code)"></ValidationMessage>
</td>
</tr>
Now, run your code, and verify whether the defamation of the EditContext.Validate()
was justified.
Update
The following code sample describes how to bind to a collection in an EditForm, and how to validate this collection as well as other fields in a model of which this collection is a field member.
Note: You should execute Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4
in your Package ManagerConsole, to access objects necessary to make the sample work...
@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; }
}
}
来源:https://stackoverflow.com/questions/65719415/how-to-get-editcontext-validate-to-work-when-binding-editform-to-an-array