
FetchIt
Легковесная AJAX-отправка форм в MODX на Fetch API поверх FormIt или своего сниппета


Маска подставляет скобки, пробелы и дефисы, пока посетитель набирает номер, и не даёт ввести лишнего. Пример на Maska — небольшой библиотеке без зависимостей.
<script src="https://cdn.jsdelivr.net/npm/maska@3/dist/cdn/maska.js" defer></script>Шаблон маски задаётся атрибутом data-maska: # — любая цифра, остальное подставляется само.
<label> Телефон
<input type="tel" name="phone" value="[[+fi.phone]]"
data-maska="+7 (###) ###-##-##"
placeholder="+7 (___) ___-__-__"
autocomplete="tel" inputmode="tel">
<span data-error="phone">[[+fi.error.phone]]</span>
</label><label> Телефон
<input type="tel" name="phone" value="{$_modx->getPlaceholder('fi.phone')}"
data-maska="+7 (###) ###-##-##"
placeholder="+7 (___) ___-__-__"
autocomplete="tel" inputmode="tel">
<span data-error="phone">{$_modx->getPlaceholder('fi.error.phone')}</span>
</label>document.addEventListener('DOMContentLoaded', () => {
new Maska.MaskInput('[data-maska]')
})
// Номер набран не до конца — не отправлять
document.addEventListener('fetchit:before', (e) => {
const { form, fetchit } = e.detail
for (const input of form.querySelectorAll('[data-maska]')) {
const mask = new Maska.Mask({ mask: input.dataset.maska })
if (input.value && !mask.completed(input.value)) {
fetchit.setError(input.name, 'Номер введён не полностью')
e.preventDefault()
}
}
})Пустое поле здесь пропускается: обязательность проверяет сервер или валидация формы.
Номер по маске всегда одной длины — 18 символов, например +7 (912) 345-67-89. Этого хватает для проверки в FormIt:
[[!FetchIt?
&form=`callback.tpl`
&hooks=`email`
&validate=`phone:required:minLength=^18^`
&vTextMinLength=`Номер введён не полностью`
]]{'!FetchIt' | snippet : [
'form' => 'callback.tpl',
'hooks' => 'email',
'validate' => 'phone:required:minLength=^18^',
'vTextMinLength' => 'Номер введён не полностью',
]}CRM и телефония часто ждут номер без оформления: +79123456789. Его можно отправить вместо того, что видит посетитель, — поле в форме не изменится:
document.addEventListener('fetchit:before', (e) => {
if (e.defaultPrevented) {
return
}
const { form, formData } = e.detail
for (const input of form.querySelectorAll('[data-maska]')) {
const digits = input.value.replace(/\D/g, '')
if (digits) {
formData.set(input.name, '+' + digits)
}
}
})Этот обработчик подключайте после проверки полноты номера. Проверку длины на сервере тогда поменяйте на minLength=^12^.