Схема валидации
Схема валидации определяет правила проверки данных формы.
Тип ValidationSchemaFn
type ValidationSchemaFn<T> = (path: FieldPath<T>) => void;
Функция валидации получает типобезопасный объект path для объявления правил:
import { GroupNode } from '@reformer/core';
import { required, email, minLength } from '@reformer/core/validators';
const form = new GroupNode({
form: {
name: { value: '' },
email: { value: '' },
},
validation: (path) => {
required(path.name);
minLength(path.name, 2);
required(path.email);
email(path.email);
},
});
FieldPath — типобезопасные пути
FieldPath<T> обеспечивает типобезопасный доступ к полям формы:
interface User {
name: string;
email: string;
address: {
city: string;
zip: string;
};
}
validation: (path: FieldPath<User>) => {
required(path.name); // ✅ Корректно
required(path.email); // ✅ Корректно
required(path.address.city); // ✅ Корректно - вложенный доступ
required(path.phone); // ❌ Ошибка TypeScript!
};
Преимущества
- Автодополнение — IDE показывает доступные поля
- Проверка на этапе компиляции — ловите опечатки заранее
- Поддержка рефакторинга — безопасное переименование полей
Встроенные валидаторы
| Валидатор | Описание |
|---|---|
required(path.field) | Поле должно иметь значение |
email(path.field) | Корректный формат email |
minLength(path.field, n) | Минимальная длина строки |
maxLength(path.field, n) | Максимальная длина строки |
min(path.field, n) | Минимальное числовое значение |
max(path.field, n) | Максимальное числовое значение |
pattern(path.field, regex) | Соответствие regex |
Полный список см. в Встроенные валидаторы.
Условная валидация
Применяйте валидаторы на основе условий:
import { when } from '@reformer/core/validators';
validation: (path) => {
required(path.email);
// Валидировать телефон только если пользователь хочет SMS
when(
() => form.controls.wantsSms.value === true,
() => {
required(path.phone);
pattern(path.phone, /^\d{10}$/);
}
);
};
Вложенная валидация
Валидация вложенных объектов и массивов:
interface Order {
customer: {
name: string;
email: string;
};
items: Array<{
product: string;
quantity: number;
}>;
}
validation: (path) => {
// Вложенный объект
required(path.customer.name);
email(path.customer.email);
// Элементы массива (валидирует шаблон каждого элемента)
required(path.items.product);
min(path.items.quantity, 1);
};
Кросс-валидация полей
Валидация полей относительно друг друга:
import { custom } from '@reformer/core/validators';
validation: (path) => {
required(path.password);
required(path.confirmPassword);
custom(path.confirmPassword, (value, ctx) => {
const password = ctx.form.password.value;
if (value !== password) {
return { match: 'Пароли должны совпадать' };
}
return null;
});
};
Асинхронная валидация
Серверная валидация:
import { asyncValidator } from '@reformer/core/validators';
validation: (path) => {
required(path.username);
asyncValidator(path.username, async (value) => {
const exists = await checkUsername(value);
if (exists) {
return { taken: 'Имя пользователя уже занято' };
}
return null;
});
};
Подробнее см. Асинхронная валидация.
Извлечение наборов валидации
Создавайте переиспользуемые функции валидации:
import { FieldPath } from '@reformer/core';
import { required, email, minLength } from '@reformer/core/validators';
// Переиспользуемый набор валидации
export function validatePerson(path: FieldPath<Person>) {
required(path.firstName);
minLength(path.firstName, 2);
required(path.lastName);
required(path.email);
email(path.email);
}
// Использование
const form = new GroupNode({
form: {
user: personSchema(),
admin: personSchema(),
},
validation: (path) => {
validatePerson(path.user);
validatePerson(path.admin);
},
});
Следующие шаги
- Обзор валидации — Подробное руководство
- Встроенные валидаторы — Все валидаторы
- Кастомные валидаторы — Создание своих
- Композиция — Переиспользование наборов валидации