Jump to main content Jump to doc navigation

Отправка формы через AJAX

FormIt может отправлять формы через AJAX без полной перезагрузки страницы. Ошибки валидации, сообщения об успехе и редиректы обрабатываются на клиентской стороне с помощью встроенной JavaScript-библиотеки.

Настройка

Для включения поддержки AJAX установите системную настройку formit.frontend_js:

Настройка Значение
formit.frontend_js js/web/formit.js

Это автоматически подключит JavaScript-файл FormIt и настроит URL AJAX-эндпоинта.

Как это работает

  1. Сниппет FormIt сохраняет свою конфигурацию (хуки, правила валидации и т.д.) в сессии/кэше на сервере и выводит MD5-хеш в плейсхолдер [[!+fi.ajaxToken]].
  2. Вы размещаете этот хеш в атрибуте data-formit-ajax-token на теге <form>.
  3. JavaScript-библиотека автоматически инициализирует все формы с этим атрибутом.
  4. При отправке формы JS перехватывает событие, отправляет данные формы + токен через fetch() на action.php.
  5. Эндпоинт извлекает исходную конфигурацию сниппета по хешу, выполняет обработку FormIt на сервере и возвращает JSON-ответ.
  6. JS обновляет DOM: отображает ошибки полей, сообщения валидации, сообщения об успехе или выполняет редирект.

Вызов сниппета

Вызов сниппета такой же, как и для обычной формы. Для AJAX не нужны специальные параметры:

[[!FormIt?
    &hooks=`email,redirect`
    &emailTpl=`MyEmailChunk`
    &emailTo=`[email protected]`
    &emailFrom=`[[++emailsender]]`
    &redirectTo=`123`
    &validate=`name:required,
        email:email:required,
        subject:required,
        text:required:stripTags`
]]

HTML формы

Чтобы форма работала через AJAX, добавьте атрибут data-formit-ajax-token на тег <form> и используйте атрибуты data-formit-* для элементов ошибок и сообщений:

<form action="[[~[[*id]]]]" method="post" class="form"
      data-formit-ajax-token="[[!+fi.ajaxToken]]">

    <div data-formit-validation-error-message>[[!+fi.validation_error_message]]</div>
    <div data-formit-success-message>[[!+fi.successMessage]]</div>

    <div class="form-field">
        <label for="name">Имя:</label>
        <input type="text" name="name" id="name" value="[[!+fi.name]]" />
        <span data-formit-error="name">[[!+fi.error.name]]</span>
    </div>

    <div class="form-field">
        <label for="email">Email:</label>
        <input type="text" name="email" id="email" value="[[!+fi.email]]" />
        <span data-formit-error="email">[[!+fi.error.email]]</span>
    </div>

    <div class="form-field">
        <label for="subject">Тема:</label>
        <input type="text" name="subject" id="subject" value="[[!+fi.subject]]" />
        <span data-formit-error="subject">[[!+fi.error.subject]]</span>
    </div>

    <div class="form-field">
        <label for="text">Сообщение:</label>
        <textarea name="text" id="text" cols="55" rows="7">[[!+fi.text]]</textarea>
        <span data-formit-error="text">[[!+fi.error.text]]</span>
    </div>

    <div class="form-field">
        <label for="numbers">Числа:</label>
        <select name="numbers" id="numbers">
            <option value="">Выберите вариант...</option>
            <option value="one" [[!+fi.numbers:FormItIsSelected=`one`]]>Один</option>
            <option value="two" [[!+fi.numbers:FormItIsSelected=`two`]]>Два</option>
            <option value="three" [[!+fi.numbers:FormItIsSelected=`three`]]>Три</option>
        </select>
        <span data-formit-error="numbers">[[!+fi.error.numbers]]</span>
    </div>

    <div class="form-field">
        <label>Цвета:</label>
        <input type="hidden" name="colors[]" value="" />
        <ul>
            <li><label><input type="checkbox" name="colors[]" value="red" [[!+fi.colors:FormItIsChecked=`red`]] /> Красный</label></li>
            <li><label><input type="checkbox" name="colors[]" value="blue" [[!+fi.colors:FormItIsChecked=`blue`]] /> Синий</label></li>
            <li><label><input type="checkbox" name="colors[]" value="green" [[!+fi.colors:FormItIsChecked=`green`]] /> Зелёный</label></li>
        </ul>
        <span data-formit-error="colors">[[!+fi.error.colors]]</span>
    </div>

    <div class="form-buttons">
        <input type="submit" value="Отправить" />
    </div>
</form>

Примечание: Атрибут action сохранён как запасной вариант на случай, если JavaScript отключён. В AJAX-режиме форма отправляется на action.php.

Справочник data-атрибутов

Атрибут Элемент Описание
data-formit-ajax-token <form> Активирует AJAX-режим. Значение должно быть [[!+fi.ajaxToken]].
data-formit-error="fieldname" <span> Отображает ошибку валидации для конкретного поля. JS заполняет innerHTML текстом ошибки.
data-formit-validation-error-message <div> Отображает общее сообщение об ошибке валидации (эквивалент [[!+fi.validation_error_message]]).
data-formit-success-message <div> Отображает сообщение об успехе (из свойства &successMessage).
data-formit-error-message <div> Отображает ошибки хуков (из [[!+fi.error_message]]).

Все элементы data-formit-error и сообщений очищаются перед каждой отправкой.

JavaScript API

Автоматическая инициализация

Формы с атрибутом data-formit-ajax-token автоматически инициализируются при событии DOMContentLoaded. Для базового использования дополнительный JavaScript не нужен.

JavaScript-события

Элемент формы отправляет CustomEvent, которые можно слушать через addEventListener. Все события всплывают (bubble).

Событие Отменяемое event.detail Описание
formit:beforesubmit Да { form } Срабатывает перед AJAX-запросом. Вызовите event.preventDefault() для отмены.
formit:success Нет { data } Срабатывает при успешной отправке.
formit:error Нет { data } Срабатывает при ошибке валидации.
formit:complete Нет {} Срабатывает после каждого запроса (успех или ошибка).
formit:redirect Да { url } Срабатывает перед редиректом. Вызовите event.preventDefault() для отмены.

Пример:

document.getElementById('my-form').addEventListener('formit:success', function (e) {
    alert('Спасибо! Ваша форма была отправлена.');
});

Обработка редиректов

Когда используется хук redirect, AJAX-режим не выполняет серверный редирект. Вместо этого:

  1. Сервер возвращает поле redirect_url в JSON-ответе.
  2. JS отправляет отменяемое событие formit:redirect.
  3. Если событие не отменено (через event.preventDefault() или возврат false из onRedirect), JS устанавливает window.location.href на URL редиректа.

Это позволяет перехватить редирект и обработать его по-своему (например, загрузить контент через AJAX, показать сообщение благодарности на месте и т.д.).

CSS-состояние загрузки

Во время AJAX-запроса:

  • CSS-класс formit-loading добавляется к элементу <form>.
  • Все кнопки [type="submit"] внутри формы получают атрибут disabled.

Оба состояния снимаются после завершения запроса.

Вы можете использовать это для стилизации индикатора загрузки:

.formit-loading {
    opacity: 0.6;
    pointer-events: none;
}

Структура JSON-ответа

Для продвинутых сценариев, AJAX-эндпоинт возвращает JSON-объект следующей структуры:

{
    "success": true,
    "message": "Сообщение об успехе или ошибке",
    "redirect_url": "https://example.com/thank-you",
    "placeholders": {
        "error.name": "<span class=\"error\">Это поле обязательно для заполнения.</span>",
        "error.email": "<span class=\"error\">Пожалуйста, введите корректный email.</span>",
        "validation_error_message": "<p class=\"error\">Произошла ошибка валидации формы.</p>",
        "successMessage": "Форма успешно отправлена."
    }
}
Поле Тип Описание
success Boolean true, если форма прошла все проверки и хуки выполнились успешно.
message String Сообщение об успехе или ошибке.
redirect_url String Присутствует только когда активен хук redirect.
placeholders Object Все плейсхолдеры FormIt (с удалённым префиксом fi.). Ошибки полей находятся в error.fieldname.

Посмотрите также

  1. Хуки
    1. FormIt.Hooks.email
    2. FormIt.Hooks.FormItAutoResponder
    3. FormIt.Hooks.math
    4. FormIt.Hooks.recaptcha
    5. FormIt.Hooks.redirect
    6. FormIt.Hooks.spam
    7. FormIt.Hooks.FormItSaveForm
  2. Валидаторы
  3. FormItRetriever
  4. Руководства и примеры
    1. Пользовательский произвольный хук
    2. Пример простой формы
    3. Обработка выпадающих списков, чекбоксов и радио кнопок
    4. Использование пустого поля для защиты от спама
  5. FormItCountryOptions
  6. FormItStateOptions

Support the team building MODX with a monthly donation.

The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.

Backers

  • modmore
  • STERC
  • Digital Penguin
  • Jens Wittmann – Gestaltung & Entwicklung
  • Fabian Christen
  • CrewMark
  • Sepia River Studios
  • Dannevang Digital
  • Alex
  • Chris Fickling
  • A. Moreno
  • Stéphane Jäggi
  • Murray Wood
  • deJaya
  • Anton Tarasov
  • JT Skaggs
  • Lefthandmedia
  • eydolan
  • Following Sea
  • YJ
  • Raffy
  • Snow Creative
  • Nick Clark
  • Guest
  • Helen
  • krisznet
  • Yanni
  • Richard

Budget

$234 per month—let's make that $500!

Learn more