Содержание
Мы уже частично познакомились с тем, как происходит валидация форм в Blazor, а также рассмотрели основные компоненты ввода для форм в Blazor. Сегодня мы более подробно рассмотрим процессы валидации форм с использованием компонентов Blazor, таких как DataAnnotationsValidator
, ValidationSummary
и ValidationMessage
.
Валидация модели в C#
Валидация модели в C#. Атрибуты валидации
Варианты валидации формы в Blazor
В Blazor валидация формы может проводиться двумя способами:
- Валидация на уровне модели. Когда пользователь заполняет все элементы формы (
InputText
,InputSelect
и т.д.) и пробует отправить форму на сервер. В этом случае, все найденные ошибки будут выведены на верху формы в виде списка. За такой вывод отвечает компонентValidationSummary
, работу с которым мы рассматривали здесь. - Когда пользователь вводит в поле какое-либо значение и переводит фокус на другой элемент формы, то производится проверка конкретного поля на правильность ввода и, в случае ошибки, сообщение выводится непосредственно под полем с ошибкой. За такое поведение отвечает компонент
ValidationMessage
Рассмотрим оба этих варианта валидации модели в Blazor Server более подробно.
Модель для приложения Blazor Server
Создадим новое приложение Blazor Server в Visual Studio 2022:
В папке приложения создадим папку Models:
В этой папке создадим новый класс Person
:
Содержимое файла Person.cs
:
using System.ComponentModel.DataAnnotations; namespace BlazorApp4.Models { public class Person { public enum GenderEnum { Male, Female} [Required] [StringLength(50, MinimumLength =2, ErrorMessage ="Имя должно быть не менее 2-х символов и не более 50-ти")] public string Name { get; set; } [Required] [Range(1, 100, ErrorMessage = "Возраст должен быть от 1 до 100 лет")] public int Age { get; set; } [Required] public GenderEnum Gender { get; set; } [EmailAddress] public string Email { get; set; } [Phone] public string PhoneNumber { get; set; } } }
Форма для модели
Для работы с созданной моделью создадим в папке Pages новый компонент Blazor с названием BlazorForm:
Содержимое файла BlazorForm.razor
:
@page "/blazorform" @using System.ComponentModel.DataAnnotations @using BlazorApp4.Models <h3>BlazorForm</h3> <EditForm Model = "person"> <DataAnnotationsValidator/> <ValidationSummary /> <div class="row mb-3"> <label for="name" class="col-sm-2 col-form-label">Имя</label> <div class="col-sm-10"> <InputText @bind-Value="person.Name" class="form-control" id="name"/> </div> </div> <div class="row mb-3"> <label for="age" class="col-sm-2 col-form-label">Возраст</label> <div class="col-sm-10"> <InputNumber @bind-Value="person.Age" class="form-control" id="age"/> </div> </div> <div class="row mb-3"> <label for="gender" class="col-sm-2 col-form-label">Пол</label> <div class="col-sm-3"> <InputSelect @bind-Value="person.Gender" id="gender" class="form-select"> <option value="Male">Мужской</option> <option value="Female">Женский</option> </InputSelect> </div> </div> <div class="row mb-3"> <label for="email" class="col-sm-2 col-form-label">E-mail</label> <div class="col-sm-10"> <InputText type="email" @bind-Value="person.Email" class="form-control" id="email"/> </div> </div> <div class="row mb-3"> <label for="phone" class="col-sm-2 col-form-label">Телефон</label> <div class="col-sm-10"> <InputText type="email" @bind-Value="person.PhoneNumber" class="form-control" id="phone"/> </div> </div> <button type="submit" class="btn btn-primary">Submit</button> </EditForm> @code { Person person = new(); }
В целом, в содержимом формы здесь для нас ничего нового нет — все моменты по работе с компонентами ввода типа InputText
или InputSelect
мы рассматривали здесь и здесь, а использование компонентов DataAnnotationsValidator
и ValidationSummary
— в этой статье. Единственное, то добавилось — это html-теги, использующие классы фреймворка bootstrap для того, чтобы форма имела более презентабельный вид. Теперь, если мы запустим приложение и перейдем на страницу /blazorform, то увидим вот такую форму:
Если мы попытаемся отправить пустую форму, то, в соответствии с атрибутами валидации, которые мы определили в модели, мы получим следующий список ошибок:
Как мы уже знаем, за вывод всего списка обнаруженных ошибок формы в Blazor отвечает компонент ValidationSummary
. Собственно, здесь мы реализовали первый вариант валидации модели, когда весь список ошибок выводится вверху формы. Теперь рассмотрим второй вариант валидации, когда проверка осуществляется по каждому полю формы в отдельности.
Компонент ValidationMessage
В отличие от ValidationSummary
компонент ValidationMessage
используется для вывода результата проверки какого-либо конкретного поля. При этом, текст ошибки выводится сразу после того, как проверяемое поле теряет фокус. Воспользоваться компонентом ValidationMessage
можно следующим образом:
<InputText @bind-Value="person.Name" class="form-control" id="name"/> <ValidationMessage For="@(() => person.Name)" />
В свойстве For
мы используем лямбда-выражение и указываем какое поле будет проверяться. Добавим ValidationMessage
к элементам нашей формы:
<EditForm Model = "person"> <DataAnnotationsValidator/> <ValidationSummary /> <div class="row mb-3"> <label for="name" class="col-sm-2 col-form-label">Имя</label> <div class="col-sm-10"> <InputText @bind-Value="person.Name" class="form-control" id="name"/> <ValidationMessage For="@(() => person.Name)" /> </div> </div> <div class="row mb-3"> <label for="age" class="col-sm-2 col-form-label">Возраст</label> <div class="col-sm-10"> <InputNumber @bind-Value="person.Age" class="form-control" id="age"/> <ValidationMessage For="@(() => person.Age)" /> </div> </div> <div class="row mb-3"> <label for="gender" class="col-sm-2 col-form-label">Пол</label> <div class="col-sm-3"> <InputSelect @bind-Value="person.Gender" id="gender" class="form-select"> <option value="Male">Мужской</option> <option value="Female">Женский</option> </InputSelect> <ValidationMessage For="@(() => person.Gender)" /> </div> </div> <div class="row mb-3"> <label for="email" class="col-sm-2 col-form-label">E-mail</label> <div class="col-sm-10"> <InputText type="email" @bind-Value="person.Email" class="form-control" id="email"/> <ValidationMessage For="@(() => person.Email)" /> </div> </div> <div class="row mb-3"> <label for="phone" class="col-sm-2 col-form-label">Телефон</label> <div class="col-sm-10"> <InputText type="email" @bind-Value="person.PhoneNumber" class="form-control" id="phone"/> <ValidationMessage For="@(() => person.PhoneNumber)" /> </div> </div> <button type="submit" class="btn btn-primary">Submit</button> </EditForm>
Теперь запустим приложение и посмотрим как будут отображаться сообщения об ошибках, если мы, например, введем отрицательное значение возраста:
Как только вводится неверное значение, то сразу же выводится сообщение об ошибке под компонентом формы и эта же ошибка отображается в сводке сверху формы. Учитывая, что дублирование сообщений об ошибках не всегда требуется, мы можем воспользоваться для валидации формы в Blazor одним из наиболее подходящих для нас вариантов: либо с использованием ValidationSummary
, либо с использованием ValidationMessage
.
Использование свойства EditContext
Выше мы использовали свойство Model
компонента EditForm
для указания модели. Вместе с этим, для EditForm
мы можем указать свойство EditContext
, благодаря которому мы получаем большую гибкость работы с формами в Blazor. Перепишем код компонента BlazorForm
следующим образом:
@page "/blazorform" @using System.ComponentModel.DataAnnotations @using BlazorApp4.Models <h3>BlazorForm</h3> <EditForm EditContext="editContext"> <--Тут весь код формы--> </EditForm> @code { Person person = new(); EditContext editContext; protected override void OnInitialized() { editContext = new EditContext(person); } }
Здесь мы переопредилили метод OnInitialized
и создали в нем объект типа EditContext
. В конструктор EditContext
мы передали объект типа Person
. У формы вместо свойства Model
мы указали свойство EditContext
которому и назначили созданный нами контекст. Теперь, если запустить приложение, то можно убедиться, что пока работа никак не изменилась — форма также валидируется и показывает ошибки ввода:
Но, как было сказано выше, использование EditContext
дает большую гибкость в работе по валидации формы в Blazor. Рассмотрим несколько вариантов использования EditContext
.
Отключение кнопки Submit
Сделаем так, чтобы в случае обнаружения ошибок в форме, кнопка Submit была не активна.
Первое: объявим переменную, которая будет хранить статус проверки формы:
@code { bool isFormValid = false; <--Остальной код--> }
Второе: отредактируем код кнопки и добавим новы атрибут:
<button type="submit" class="btn btn-primary" disabled="@isFormValid">Submit</button>
Третье: обновим код компонента BlazorForm следующим образом:
@code { private bool isFormValid = false; private Person person = new(); EditContext editContext; protected override void OnInitialized() { editContext = new EditContext(person); editContext.OnFieldChanged += FieldChanged; /* или, используя лямбда-выражение editContext.OnFieldChanged += (x, y) => { isFormValid = !editContext.Validate(); }; */ } private void FieldChanged(object sender, FieldChangedEventArgs args) { isFormValid = !editContext.Validate(); } }
здесь мы назначили объекту EditContext
обработчик события OnFileldChanged
, которое срабатывает при каждом изменении поля формы. В зависимости от того, с каким результатом завершается валидация мы устанавливаем значение переменной isFormValid
. Теперь запустим приложение и попробуем допустить какую-либо ошибку в форме:
Как можно убедиться, при ошибочном вводе какой-либо информации кнопка Submit становится не активной. Однако, при этом вся форма проходит валидацию, что, соответственно, влечет за собой вывод сразу всех ошибок в форме, даже, если пользователь ещё не начинал вводить данные в какое-либо поле.
Использование события OnSubmit
Когда мы используем свойство EditForm.Model
то вызов OnSubmit
сразу отправляет данные на сервер вне зависимости от того есть ли в форме ошибки или нет. С использованием EditForm.EditContext
мы можем избежать отправки на сервер формы, содержащей ошибки следующим образом:
<EditForm EditContext="editContext" OnSubmit="SubmitForm"> <DataAnnotationsValidator/> <ValidationSummary /> <--тут код формы--> </EditForm> @code { private bool isFormValid = false; private Person person = new(); EditContext editContext; protected override void OnInitialized() { editContext = new EditContext(person); } public void SubmitForm() { if (editContext.Validate()) { //логика сохранения формы, например, в БД } } }
Итого
Сегодня мы рассмотрели два варианта валидации форм в приложении Blazor Server. Результаты проверки могут выводится как в виде сводки (списка) вверху формы, так и по каждому полю формы в отдельности. Для более гибкого управления процессом валидации и отправки формы можно использовать свойство EditForm.EditContext
.