В данной заметке мы вам покажем как подружить компонент FetchIt с популярной библиотекой yup и реализовать дополнительную валидацию на стороне клиента. Допустим, что нам необходимо обработать несложную форму с двумя полями, имя и возраст. И логика будет заключаться в том, если пользователь указывает свой возраст и он оказывается ниже 18-ти то мы не дадим отправить форму и покажем сообщение.
Подключение библиотеки
У нас есть возможность импортировать библиотеку из CDN. Но помните, в продакшене такой способ лучше не использовать.
<script type="module">
import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm';
</script>
Добавление обработчика
Нам нужно отловить момент до отправки формы и для этого добавим обработчик на событие
fetchit:before
.html<script type="module"> import * as yup from 'https://cdn.jsdelivr.net/npm/yup@1/+esm'; document.addEventListener('fetchit:before', (e) => { }); </script>
В данном событии мы можем получить доступ к данным формы и экземпляру класса FetchIt и именно это нам нужно сделать.
html<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>
Теперь нам необходимо преобразовать
formData
в обычный объект.html<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>
Затем, напишем схему по которой будет валидироваться наша форма и сразу же укажем сообщения об ошибках.
html<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-ти и целым.
Внимание
Библиотека yup предоставляет несколько способов локализации текстов ошибок. Для примера мы выбрали самый простой.
Узнать о всех возможностях можно в документации.
Вызовем метод валидации
validateSync()
нашей схемы в блокеtry..catch
для того чтобы мы могли отлавливать неудачные попытки.html<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>
Затем обратим внимание на блок catch, т.к. там мы и будем отлавливать все ошибки валидации и с помощью метода
setError()
экземпляра классаFetchIt
устанавливать невалидное состояние полям. Также вызовем методpreventDefault()
события для того, чтобы прервать отправку формы.html<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>
Также по желанию вы можете показать всплывающее сообщение об ошибке и делается это очень просто.
html<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=`Тема письма`
]]
Вы также можете ознакомиться с примером интеграции с другой библиотекой iodine в документации компонента.
Спасибо всем за внимание!