[FetchIt] - Дополнительная валидация с помощью библиотеки yup
В данной заметке я расскажу как подружить компонент FetchIt с популярной библиотекой yup и реализовать дополнительную валидацию на стороне клиента.
Допустим, что нам необходимо обработать несложную форму с двумя полями, имя и возраст. И логика будет заключаться в том, если пользователь указывает свой возраст и он оказывается ниже 18-ти то мы не дадим отправить форму и покажем сообщение.

У нас есть возможность импортировать библиотеку из CDN. Но помните, в продакшене такой способ лучше не использовать.
1. Добавим обработчик на событие fetchit:before.
2. В данном событии мы можем получить доступ к данным формы и экземпляру класса FetchIt и именно это нам нужно сделать.
3. Теперь нам необходимо преобразовать formData в обычный объект.
4. Затем, напишем схему по которой будет валидироваться наша форма и сразу же укажем сообщения об ошибках.
Как вы видите, мы указали, что наша схема должна быть объектом с ключами:
Узнать о всех возможностях можно в документации.
5. Вызовем метод валидации validateSync() нашей схемы в блоке try..catch для того чтобы мы могли отлавливать неудачные попытки.
6. Затем обратим внимание на блок catch, т.к. там мы и будем отлавливать все ошибки валидации и с помощью метода setError() экземпляра класса FetchIt устанавливать невалидное состояние полям. Также вызовем метод preventDefault() события для того, чтобы прервать отправку формы.
7. Также по желанию вы можете показать всплывающее сообщение об ошибке и делается это очень просто.
Вот и всё! После этих шагов мы получим валидацию с использованием библиотеки yup, но помните, на стороне клиента она небезопасна. И поэтому при вызове сниппета нужно воспользоваться средствами валидации FormIt или если вы используете собственный сниппет, то производить её в нём.
Пример вызова сниппета с валидацией FormIt:
Вы сможете сейчас скачать бесплатно компонент с modstore.pro и modx.com с последними фиксами.
Всем мира и спасибо за внимание!
Документация
Репозиторий на GitHub
☕ Угостить чашкой кофе
Допустим, что нам необходимо обработать несложную форму с двумя полями, имя и возраст. И логика будет заключаться в том, если пользователь указывает свой возраст и он оказывается ниже 18-ти то мы не дадим отправить форму и покажем сообщение.

Подключение библиотеки
У нас есть возможность импортировать библиотеку из CDN. Но помните, в продакшене такой способ лучше не использовать.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
</script>Добавление обработчика
1. Добавим обработчик на событие fetchit:before.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
});
</script>2. В данном событии мы можем получить доступ к данным формы и экземпляру класса FetchIt и именно это нам нужно сделать.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
});
</script>3. Теперь нам необходимо преобразовать formData в обычный объект.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
const fields = Object.fromEntries(formData.entries());
});
</script>4. Затем, напишем схему по которой будет валидироваться наша форма и сразу же укажем сообщения об ошибках.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
const fields = Object.fromEntries(formData.entries());
const formSchema = yup.object({
name: yup
.string()
.required('Введите своё имя'),
age: yup
.number()
.required('Введите свой возраст')
.min(18, 'Вам должно быть 18 лет')
.integer()
.typeError('Поле должно быть числом'),
});
});
</script>Как вы видите, мы указали, что наша схема должна быть объектом с ключами:
- name — значение которого должно быть строкой и оно обязательное.
- age — значение которого должно быть числом, оно обязательное, должно быть больше 18-ти и целым.
Узнать о всех возможностях можно в документации.
5. Вызовем метод валидации validateSync() нашей схемы в блоке try..catch для того чтобы мы могли отлавливать неудачные попытки.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
const fields = Object.fromEntries(formData.entries());
const formSchema = yup.object({
name: yup
.string()
.required('Введите своё имя'),
age: yup
.number()
.required('Введите свой возраст')
.min(18, 'Вам должно быть 18 лет')
.integer()
.typeError('Поле должно быть числом'),
});
try {
formSchema.validateSync(fields, { abortEarly: false });
} catch (err) {
}
});
</script>6. Затем обратим внимание на блок catch, т.к. там мы и будем отлавливать все ошибки валидации и с помощью метода setError() экземпляра класса FetchIt устанавливать невалидное состояние полям. Также вызовем метод preventDefault() события для того, чтобы прервать отправку формы.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
const fields = Object.fromEntries(formData.entries());
const formSchema = yup.object({
name: yup
.string()
.required('Введите своё имя'),
age: yup
.number()
.required('Введите свой возраст')
.min(18, 'Вам должно быть 18 лет')
.integer()
.typeError('Поле должно быть числом'),
});
try {
formSchema.validateSync(fields, { abortEarly: false });
} catch (err) {
e.preventDefault();
for (const { path, message } of err.inner) {
fetchit.setError(path, message);
}
}
});
</script>7. Также по желанию вы можете показать всплывающее сообщение об ошибке и делается это очень просто.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
document.addEventListener('fetchit:before', (e) => {
const { formData, fetchit } = e.detail;
const fields = Object.fromEntries(formData.entries());
const formSchema = yup.object({
name: yup
.string()
.required('Введите своё имя'),
age: yup
.number()
.required('Введите свой возраст')
.min(18, 'Вам должно быть 18 лет')
.integer()
.typeError('Поле должно быть числом'),
});
try {
formSchema.validateSync(fields, { abortEarly: false });
} catch (err) {
e.preventDefault();
for (const { path, message } of err.inner) {
fetchit.setError(path, message);
}
FetchIt.Message.error('Исправьте ошибки в форме'); // Показать всплывающее сообщение
}
});
</script>Вот и всё! После этих шагов мы получим валидацию с использованием библиотеки yup, но помните, на стороне клиента она небезопасна. И поэтому при вызове сниппета нужно воспользоваться средствами валидации FormIt или если вы используете собственный сниппет, то производить её в нём.
Пример вызова сниппета с валидацией FormIt:
[[!FetchIt?
&form=`form.tpl`
&hooks=`email,FormItSaveForm`
&validate=`name:required,age:required:isNumber:minValue=^18^`
// Необязательные параметры
&snippet=`FormIt`
&formName=`Название формы`
&emailSubject=`Тема письма`
]]Вы сможете сейчас скачать бесплатно компонент с modstore.pro и modx.com с последними фиксами.
Всем мира и спасибо за внимание!
Документация
Репозиторий на GitHub
☕ Угостить чашкой кофе
Комментарии: 15
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Но проблема в том, что конфиг генерируется во время рендера страницы. Так уж задумано. Я подумаю как можно облегчить такие задачи в будущем
1. Помни, это может поменяться, обращай внимания на обновления FetchIt
2. Пиши так:
Js ванилу не так давно начал, поэтому такие огрехи встречаются :)
Это что какой-то поддерживаемый синоним объекта document?
Не знаю зачем ему она, видимо для того чтобы писать короче
Сам пользуюсь сниппетом, который аяксом обновляет чанк (на самом деле нет, это кастомный блок для zoomx, но так понятнее). И формы можно отправлять через formit, и фильтры делать. Не планируете расширять функционал, чтоб можно было чанки загружать? Название как раз к этому располагает) Мне самому не нужно, но думаю многим пригодится, пару раз видел тут, какие люди костыли городят для такого
Пока в планах такого нет, но всё может изменится