#blazor #blazor-server-side
#blazor #blazor-на стороне сервера
Вопрос:
Я создал EditForm
обертку таблицы следующим образом:
**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();
}
}
Сообщение об ошибке появляется правильно, как показано на рисунке ниже:
Однако, когда я отправляю форму, а затем проверяю, она, похоже, не распознает недопустимое состояние.
Он по-прежнему возвращает значение true после вызова EditContext.Validate()
, даже несмотря на наличие ошибок.
Как мне заставить это работать? (Как мне получить false, если хотя бы один элемент модели в контексте EditForm является недопустимым, чтобы я мог выполнить другие действия по проверке?)
[Обновлено 2021-01-16] Ответы также можно найти здесь. https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor /
Короче говоря, встроенная функция DataAnnotationValidation не работает с массивами. Чтобы заставить его работать, вы должны
- Установите Microsoft.AspNetCore.Компоненты.Примечания к данным.Проверка
- Сделайте массив атрибутом, а затем украсьте его [ValidateComplexType]
- Используйте ObjectGraphDataAnnotationsValidator
Комментарии:
1. По этой ссылке: docs.microsoft.com/en-us/aspnet/core/blazor /… , вы должны создать новый EditContext в процедуре OnInitialized() для формы (editContext = новый EditContext(vms). Возможно, это поможет вам
2. Я согласен с @JasonD , тогда, когда вы хотите проверить, что вы могли бы использовать: if (editContext .Validate()) {//SomeLogic}
Ответ №1:
Во-первых, я бы посоветовал вам сделать что-то вроде этого
<EditForm EditContext="editContext" OnSubmit="Submit">
Вместо
<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
Что требует от вас определения EditContext следующим образом: EditContext editContext;
И создайте экземпляр объекта EditContext в инициализированном методе следующим образом:
protected override void OnInitialized()
{
vms = new List<MyClass>() { new MyClass() { Code = "1111" },
new MyClass() { Code = "2222" }
};
editContext = new EditContext(vms);
}
Кстати, почему вы используете OnSubmit
вместо OnValidSubmit
and OnInvalidSubmit
? Вы ищете проблемы?
EditContext.Validate() возвращает неправильные результаты
Это неверно…
Проблема в том, что вы пытаетесь выполнить привязку к массиву 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
в вашем Package ManagerConsole, чтобы получить доступ к объектам, необходимым для выполнения примера…
@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; }
}
}
Комментарии:
1. Спасибо за ответ. Однако проблема, с которой я сталкиваюсь, заключается в том, что я хочу достичь следующих двух целей одновременно: 1. Привязка к списку 2. Заставить EditContext.Validate() работать. Я попробовал ваше предложение о создании класса-оболочки, а затем включить список MyClass в оболочку в качестве свойства, но аннотация данных перестает работать после того, как я это сделаю. Возможно, мне следует лучше сформулировать свои вопросы, например «Как заставить EditContext.Validate() работать при привязке EditForm к массиву».
2. Смотрите Раздел Обновления в моем ответе. Не могли бы вы пометить его как ответ, если он решил вашу проблему, чтобы другие знали, что это было полезно.