пример - проверяем что уже зарегистрирован пользователь с таким email
validate({
field: form.fields.email,
trigger: ["blur"], // эта валидация нам тоже нужна не часто
// rules для запуска всяких синхронных штук, а target - для запуска эвентов и эффектов для валидации
// по идее такой же target как в операторе sample
// (или тоже включить в rules, если получится прокинуть такое)
target: checkEmailFx
})
пояснение
для каждого поля надо добавить стор $validating: boolean, который выставляется во время асинхронной валидации
если effect checkEmailFx завершится с ошибкой - поле считается невалидным с текстом ошибки, который упал в failData
В этом кейсе можно подумать над тем как использовать что-то из экосистемы, например, farfetched - вызывать не эффект а событие query.start, и добавить оператор для этого, чтобы ручками не выставлять для поля всякие стейты $validated и не ловить и не прокидывать потом результат валидации в него
пример - тоже самое, "но ручками" через события, а не эффект
import { createQuery } from "@farfetched/farfetched-core";
const checkEmailQuery = createQuery(...);
const checkEmailQueryEvent = createEvent<{ value: string }>();
sample({
clock: checkEmailQueryEvent,
fn: ({ value }) => ..., // по-сути это mapParams
target: checkEmailQuery.start
});
// запускаем валидацию - проверку что такой email уже существует
validate({
field: form.fields.email,
trigger: ["blur"],
target: checkEmailQueryEvent
});
sample({
// пусть для примера тут ответ 200 OK, но в теле есть инфо о том что пользователь с таким емейлом уже зареган
clock: checkEmailQuery.finished.success,
filter: ({ result }) => Boolean(result.error),
fn: ({ result }): string => result.error?.message,
target: form.fields.email.invalidate // вообще changeError, но это название имхо не очень
});
по-идее в перспективе в farfetched или других либах можно будет делать фабрики на что-то подобное
запуск сторонней логики
тут оператор validate не при чем, можно обойтись sample
пример
если начали вводить passwordConfirm, а поле password ещё не заполнено - подсветим поле password
sample({
clock: form.fields.passwordConfirm.changed,
source: form.$values,
filter: values => values.password.length === 0 && values.passwordConfirm.length > 0,
// запуск правил валидации для поля password, которые вернут ошибку "password is required"
target: form.fields.password.validate
})
Валидация для ArrayField
тут есть два случая
1) поля типа ArrayField в value при запуске проверки правила валидации передают номер элемента для которого происходит вызов валидатора
validate({
field: fields.addresses,
rules: [
({ value, index }) => index > 5 ? "у вас слишком много адресов" : undefined
]
})
2) валидация прям всего массива (специальный оператор который смотрит на массив как на массив)
или может быть аргумент array: true в операторе validate
// или validateArray или validate({ field: ArrayField, array?: true }) чтобы отличать валидацию всего списка от валидации поля в списке
validateArray({
field: fields.addresses,
rules: [
// requiredArray
({ value, length }) => length === 0 ? "должен быть хотя бы один адрес" : undefined
]
});
тут придется ещё сделать доработки в useArrayField - чтобы этот хук также мог возвращать ошибки и статус валидации для всего списка
Хочется декларативно описывать валидации полей, но не в схеме (очень плохо смотрится для больших форм)
пример
плюшки
значения других сторов для валидации, и запуск валидации только по условию
пример - валидация поля passwordConfirm: работает только если введён пароль и проверяет совпадение с ним
асинхронная валидация
пример - проверяем что уже зарегистрирован пользователь с таким email
пояснение
$validating: boolean
, который выставляется во время асинхронной валидациипример - тоже самое, "но ручками" через события, а не эффект
по-идее в перспективе в farfetched или других либах можно будет делать фабрики на что-то подобное
запуск сторонней логики
тут оператор validate не при чем, можно обойтись sample
пример если начали вводить passwordConfirm, а поле password ещё не заполнено - подсветим поле password
Валидация для ArrayField
тут есть два случая
1) поля типа ArrayField в value при запуске проверки правила валидации передают номер элемента для которого происходит вызов валидатора
2) валидация прям всего массива (специальный оператор который смотрит на массив как на массив) или может быть аргумент
array: true
в оператореvalidate
тут придется ещё сделать доработки в
useArrayField
- чтобы этот хук также мог возвращать ошибки и статус валидации для всего списка