Для программной валидации данных формы можно использовать объект EditContext и его функционал. В частности, с помошью его метода
Validate() можно проверять валидность введенных данных - если они корректны, то метод возвращает true
. Где мы можем это использовать?
Компонент EditForm
предоставляет три метода для отправки данных формы
OnValidSubmit срабатывает, если нет ошибок валидации
OnInvalidSubmit срабатывает, если есть ошибки валидации
OnSubmit срабатывает вне зависимости от наличия ошибок валидации
Если для отправки формы применяется метод OnSubmit
, то мы можем использовать метод EditContext.Validate()
для проверки на валидность перед отправкой.
Пусть у нас в проекте есть класс Person, который представляет данные, и два компонента - App и Home:
Класс Person будет представлять используемую модель данных:
using System.ComponentModel.DataAnnotations; public class Person { [Required] [StringLength(20, MinimumLength = 2)] public string Name { get; set; } = ""; [Required] [Range(1, 110)] public int Age { get; set; } }
Пусть компонент App представляет корневой компонент и просто выводит на страницу компонент Home:
@page "/" <!DOCTYPE html> <html> <head> <title>METANIT.COM</title> <meta charset="utf-8" /> </head> <body> <Home /> <script src="_framework/blazor.web.js"></script> </body> </html>
А в компоненте Home определим код формы и программной проверки на валидность:
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Forms @rendermode RenderMode.InteractiveServer <EditForm EditContext="editContext" OnSubmit="Submit"> <DataAnnotationsValidator /> <ValidationSummary /> <p> Name:<br /> <InputText id="name" @bind-Value="person.Name" /> </p> <p> Age:<br /> <InputNumber id="age" @bind-Value="person.Age" /> </p> <button type="submit">Submit</button> </EditForm> <h3>@message</h3> @code { string message = ""; Person person = new(); EditContext? editContext; protected override void OnInitialized() { editContext = new(person); } void Submit() { if (editContext != null && editContext.Validate()) message = $"Name: {person.Name}; Age: {person.Age}"; else message = "Data Invalid"; } }
Для установки объекта EditContext у класса EditForm применяется одноименное свойство
<EditForm EditContext="editContext"
Здесь объект EditContext создается в методе OnInitialized()
, который вызывается при инициализации компонента:
Person person = new(); EditContext? editContext; protected override void OnInitialized() { editContext = new(person); }
В методе Submit()
, который вызывается по нажатию на кнопку, проверяем валидность данных, вызывая у EditContext метод Validate()
void Submit() { if (editContext!=null && editContext.Validate()) message = $"Name: {person.Name}; Age: {person.Age}";
Если нам надо, чтобы нажатие на кнопку не срабатывало, если данные не корректны, то проще всего использовать событие OnValidSubmit
:
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Forms @rendermode RenderMode.InteractiveServer <EditForm EditContext="editContext" OnValidSubmit="ValidSubmit"> <DataAnnotationsValidator /> <ValidationSummary /> <p> Name:<br /> <InputText id="name" @bind-Value="person.Name" /> </p> <p> Age:<br /> <InputNumber id="age" @bind-Value="person.Age" /> </p> <button type="submit">Submit</button> </EditForm> <h3>@message</h3> @code { string message = ""; Person person = new(); void ValidSubmit() { message = $"Name: {person.Name}; Age: {person.Age}"; } }
Теперь, пока не будут введены корректные данные, метод ValidSubmit выполняться не будет.
Класс EditContext предоставляет событие OnValidationStateChanged, которое позволяет отслеживать состояние валидации. Данное событие срабатывает при каждом изменении значений в полях ввода. Соответственно здесь мы можем проверить различные данные, связанные с валидацией, или выполнить какие-то действия, например, добавить кастомную логику валидации. Рассмотрим небольшой пример. Пусть в компоненте Home будет прописан следующий код:
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Forms @rendermode RenderMode.InteractiveServer @implements IDisposable <EditForm EditContext="editContext" OnSubmit="Submit"> <DataAnnotationsValidator /> <ValidationSummary /> <p> Name:<br /> <InputText id="name" @bind-Value="person.Name" /> </p> <p> Age:<br /> <InputNumber id="age" @bind-Value="person.Age" /> </p> <button type="submit">Submit</button> </EditForm> <h3>@message</h3> @code { string message = ""; Person person = new(); EditContext? editContext; ValidationMessageStore? messageStore; // хранилище сообщений об ошибках protected override void OnInitialized() { editContext = new(person); messageStore = new(editContext); // связываем хранилище сообщений с контекстом EditContext editContext.OnValidationStateChanged += HandleValidationRequested; } void HandleValidationRequested(object? sender, ValidationStateChangedEventArgs args) { messageStore?.Clear(); // удаляем ранее добавленные сообщения // если имя - admin, добавляем сообщение обошибке if (person.Name == "admin") messageStore?.Add(() => person.Name!, "Invalid name"); } public void Dispose() { if (editContext != null) editContext.OnValidationStateChanged -= HandleValidationRequested; } void Submit() { if (editContext != null && editContext.Validate()) message = $"Name: {person.Name}; Age: {person.Age}"; else message = "Data Invalid"; } }
В данном случае будем считать, что имя "admin" - недействительное. И нам надо как-то уведомить об этом пользователя. Для этого определяем хранилище сообщений об ошибках - объект ValidationMessageStore:
ValidationMessageStore? messageStore;
Конструктор этого класса принимает контекст EditContext, с которым ассоциируется это хранилище сообшений. И в методе OnInitialized()
создаем это хранилище:
messageStore = new(editContext);
Чтобы отслеживать изменение состояния валидации, также в методе OnInitialized()
подписываемся на событие OnValidationStateChanged
editContext.OnValidationStateChanged += HandleValidationRequested;
В методе-обработчике HandleValidationRequested добавляем в хранилище сообщений одно сообщение, если введенное имя равно "admin":
void HandleValidationRequested(object? sender, ValidationStateChangedEventArgs args) { messageStore?.Clear(); // удаляем ранее добавленные сообщения if (person.Name == "admin") messageStore?.Add(() => person.Name!, "Invalid name"); }
Прежде чем добавить сообщения, мы очищаем хранилище сообшений с помошью метода Clear()
. А для добавления сообщения применяется метод Add()
.
Первый параметр метода Add()
- делегат, который определяет свойство валидируемого объекта (в данном случае свойство Name). Второй параметр - собственно сообщение об ошибке в виде строки.
И как и в случае с любыми другими событиями, нам надо отписаться от события OnValidationStateChanged в методе Dispose()
:
@implements IDisposable // реализуем интерфейс IDisposable public void Dispose() { if(editContext != null) editContext.OnValidationStateChanged -= HandleValidationRequested; }
И теперь имя "admin" будет считаться недействительным: