Здравствуйте друзья!
Попросили подправить форму обратной связи, не отправляет письма.
Вызывается ошибка «Форма содержит ошибки» и красным подсвечивается форма с Почтой, типа адрес почты не правильный или отсутствует…
Форма выводится двумя дополнениями FormIt и AjaxForm
Вот стандартный код который гуляет в сети.
Создаем Чанк tpl.AjaxForm
с кодом
<form action="" method="post" class="ajax_form af_example form-horizontal">
<div class="control-group">
<label class="control-label" for="af_name">Имя*</label>
<div class="controls">
<input type="text" id="af_name" name="name" value="" placeholder="Введите имя">
<span class="error_name"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="af_email">E-mail*</label>
<div class="controls">
<input type="email" id="af_email" name="email" value="" placeholder="Введите email">
<span class="error_email"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="af_phone">Телефон</label>
<div class="controls">
<input type="text" id="af_phone" name="phone" value="" placeholder="Введите номер телефона">
<span class="error_phone"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="af_message">Сообщение*</label>
<div class="controls">
<textarea id="af_message" name="message" rows="5"></textarea>
<span class="error_message"></span>
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="reset" class="btn btn-default">Очистить</button>
<button type="submit" class="btn btn-primary">Отправить</button>
</div>
</div>
</form>
Вызов сниппета AjaxForm на странице контактов
[[!AjaxForm?
&form=`tpl.AjaxForm`
&snippet=`FormIt`
&hooks=`FormItSaveForm,email`
&emailSubject=`Тестовое сообщение`
&emailTo=`myemail@mail.ru`
&emailFrom=`no-reply@mysite.com`
&emailTpl=`tpl.email`
&validate=`name:minLength=^2^,email:email:required,message:minLength=^10^`
&validationErrorMessage=`В форме содержатся ошибки!`
&successMessage=`Сообщение успешно отправлено`
]]
Чанк tpl.email с шаблоном самого письма
<h3>Сообщение</h3>
<p>От кого: [[+name]]</p>
<p>E-mail: [[+email]]</p>
<p>Телефон: [[+phone]]</p>
<p>Сообщение: [[+message]]</p>
И не работает, кучу подобный перепробовал, результат тот же.
Подскажите пожалуйста, как решить проблему?
Спасибо!
В этой статье рассмотрим процесс создания формы обратной связи на MODX с использованием FormIt. А также работу с ней через Ajax посредством AjaxForm.
О компоненте FormIt
В репозитории MODX имеется очень популярное дополнение для динамической обработки форм. Называется оно FormIt.
Это дополнение используется для обработки формы после нажатия на кнопку отправки. FormIt сначала выполняет валидацию, и только затем (после успешной проверки) другие действия. Например, такие как отправка сообщения на электронную почту, сохранение данных формы в базу данных, функцию автоответчика и др.
Установить пакет FormIt можно из главного репозитория modx.com/extras/package/formit.
Пример простой формы обратной связи на FormIt
В этом примере создадим простую HTML форму с использованием Bootstrap 5. Она будет состоять из 3 полей: имя, email и сообщение. FormIt будет выполнять валидацию формы и отправлять сообщение с данными, которые ввел пользователь, на email.
Вызов сниппета FormIt
:
[[!FormIt?
&emailFrom=`[[++emailsender]]`
&emailTo=`alexander@mail.com`
&emailTpl=`myEmailTpl`
&hooks=`email`
&submitVar=`feedback-form`
&successMessage=`Форма успешно отправлена!`
&validate=`nospam:blank,
name:required,
email:email:required,
message:required:minLength=^20^`
]]
Список используемых параметров:
hooks
– список скриптов, которые нужно выполнить после успешной валидации формы; скрипты будут запускаться последовательно друг за другом; если какой-то скрипт завершится не удачно, то следующие за ним выполняться не будут;validate
– список полей, которые нужно проверить на соответствии указанным требованиям; можно указать несколько валидаторов, например, как это сделано дляemail
;submitVar
– необходим, чтобы этот вызов сниппетаFormIt
обрабатывал не все формы, а только те, которые содержат указанный ключ в составе передаваемых на сервер данных (в суперглобальном массиве$_POST
);successMessage
– сообщение, которое необходимо вывести после успешного завершения обработки формы; работает, только если не используется свойство для редиректа;emailTpl
– чанк, содержащий шаблон email письма;emailTo
– адрес, на который нужно отправить email;emailFrom
– адрес, от которого будет отправлен email; в этом примере email будем брать из системного параметраemailsender
;emailSubject
– тема письма.validationErrorMessage
– сообщение, которое нужно вывести, если в форме содержатся ошибки.
Работает FormIt
следующим образом:
1. Получает данные формы. Так как в вызове сниппета FormIt
, мы указали свойство submitVar
, то этот сниппет будет обрабатывать только ту форму, которая будет передавать в теле запроса этот ключ. Его мы добавили к кнопке type="submit"
.
2. Выполняет валидацию. После этого выполняется валидация формы в соответствии с требованиями, которые мы указали в свойстве validate
. Валидатор в этом свойстве задаётся через двоеточие.
Валидатор blank
проверяет, является ли поле пустым. В данном примере мы проверяем с помощью него поле nospam
:
nospam:blank
Кроме blank
в этом примере ещё используются следующие валидаторы:
required
– проверяет, является ли поле не пустым;email
– содержит ли поле корректный адрес электронной почты;minLength
– требование, к минимальному количеству символов.
Например, для проверки поля email
мы используем 2 валидатора:
email:email:required
Таким образом это поле должно быть не пустым и содержать корректный email.
Если какие-то поля не прошли валидацию, то ошибки будут выведены в соответствующие плейсхолдеры. Например, для поля email
это будет:
[[+fi.error.email]]
3. Выполнение хуков. После успешной валидации будут последовательно друг за другом выполнены скрипты, указанные в hooks
.
В приведённом примере мы используем в hooks
только один скрипт: email
. Он отправит форму на email. Шаблон для этого письма он возьмёт из чанка, заданного в emailTpl
. А отправит он письмо на email, указанный в свойстве emailTo
.
4. Вывод сообщения об успехе. После успешного завершения хука email
будет выведено в плейсхолдер fi.successMessage
сообщение, указанное в свойстве successMessage
.
HTML код формы:
[[!+fi.successMessage:notempty=`<div class="alert alert-success" role="alert">[[!+fi.successMessage]]</div>`]]
<form action="[[~[[*id]]]]" method="post" class="form">
<input type="hidden" name="nospam" id="nospam" value="">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control[[!+fi.error.name:notempty=` is-invalid`]]" name="name" id="name" value="[[!+fi.name]]">
<div class="invalid-feedback">[[!+fi.error.name]]</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control[[!+fi.error.email:notempty=` is-invalid`]]" name="email" id="email" value="[[!+fi.email]]">
<div class="invalid-feedback">[[!+fi.error.email]]</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="tel" class="form-control[[!+fi.error.phone:notempty=` is-invalid`]]" name="phone" id="phone"
value="[[!+fi.phone]]">
<div class="invalid-feedback">[[!+fi.error.phone]]</div>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control[[!+fi.error.message:notempty=` is-invalid`]]" name="message" id="message"
rows="5">[[!+fi.message]]</textarea>
<div class="invalid-feedback">[[!+fi.error.message]]</div>
</div>
<div class="mb-3">
<input type="submit" class="btn btn-primary" name="feedback-form" value="Отправить">
</div>
</form>
Оформление формы выполнено на Bootstrap 5.
Скрытое поле nospam
используется для защиты от спама. Обычно спам боты пытаются заполнить все поля, а это поле должно быть пустым. Если поле nospam
не пустое, то форма не пройдёт проверку и её дальнейшая обработка выполняться не будет.
Сниппет FormIt
будет заполнять в форме заданные плейсхолдеры. Например, для поля email
:
fi.email
– значением поляemail
;fi.error.email
– сообщением об ошибке при валидации.
Выделение полей, которые не прошли валидацию, выполняется посредством добавления к ним класса is-invalid
. Например, для поля email
это будет выглядеть так:
[[!+fi.error.email:notempty=` is-invalid`]]
Т.е. когда плейсхолдер fi.error.email
не пустой, у элемента <input>
появится класс is-invalid
.
Для вывода сообщения об успешной обработки формы используется следующая конструкция:
[[!+fi.successMessage:notempty=`<div class="alert alert-success" role="alert">[[!+fi.successMessage]]</div>`]]
Она работает очень просто: если плейсхолдер fi.successMessage
что-то содержит, то выведи HTML блок с содержимым [[!+fi.successMessage]]
:
<div class="alert alert-success" role="alert">[[!+fi.successMessage]]</div>
Этот HTML блок является компонентом Alert фреймворка Bootstrap.
В теге <form>
для атрибута action
укажем URL на эту же страницу:
<form action="[[~[[*id]]]]" method="post">
Содержимое чанка myEmailTpl
:
<p style="font-weight: bold;">Сообщение с формы обратной связи.</p>
<p><mark>[[+name]]</mark> (email: <mark>[[+email]]</mark>, phone: <mark>[[+phone:default=`-`]]</mark>) оставил следующее сообщение:</p>
<p style="background-color: #eee; padding: 15px;">[[+message]]</p>
Отправка формы через AJAX
По умолчанию FormIt
не умеет работать с формой через AJAX. Но в репозитории modstore.pro имеется дополнение AjaxForm
, которое позволяет отправлять формы через AJAX. По умолчанию оно работает с FormIt
. Но при необходимости вместо FormIt
можно использовать собственный сниппет.
При использовании AjaxForm
работа с формой будет осуществляться следующим образом:
- вывод HTML формы будет осуществляться из чанка, который передан
AjaxForm
в свойствеform
; - отправка форма выполняется через AJAX, для этого сниппет
AjaxForm
регистрирует на фронтенде нужные скрипты; - на сервере запускает сниппет
FormIt
и передаёт ему данные формы; - после получения ответа от
FormIt
передаёт его браузеру, который выводится пользователю на страницу с использованием JavaScript.
Перед тем как начать переделывать форму проверим установлено ли у нас расширение AjaxForm
.
Ход работы:
1. Создадим чанк myFormTpl
и вставим в него HTML код формы.
AjaxForm вывод сообщений об ошибках, например, для поля email
, осуществляет в элемент с классом error_mail
. Кроме этого, к полям, которые не прошли валидацию добавляет класс error
.
Но нас это не устраивает, т.к. сообщения об ошибке нужно помещать в элемент с классом invalid-feedback
, а к полям, которые не прошли проверку необходимо добавлять класс is-invalid
.
Это мы будем выполнять с помощью JavaScript при получении ответа от сервера:
$(document).on('af_complete', function (event, response) {
const elForm = $(response.form);
elForm.find('.is-invalid').each(function (index, el) {
$(el).removeClass('is-invalid');
});
for (let key in response.data) {
const elInput = elForm.find(`[name=${key}]`);
elInput.addClass('is-invalid');
elInput.next('.invalid-feedback').text($(response.data[key]).text());
}
});
После этого из формы необходимо удалить плейсхолдеры [[!+fi.name]]
, [[!+fi.error.name]]
и др. Они используются в качестве заполнителей для сниппета FormIt
и позволяют нам сохранять значения, введённые пользователем и отображать ошибки валидации. Но так как сейчас работа ведётся через AJAX, то они нам не нужны.
В итоге HTML форма будет иметь следующий код:
<form action="#" method="post" class="feedback-form">
<input type="hidden" name="nospam" id="nospam">
<div class="mb-3">
<label for="name" class="form-label">Имя</label>
<input type="text" class="form-control" name="name" id="name">
<div class="invalid-feedback"></div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" name="email" id="email">
<div class="invalid-feedback"></div>
</div>
<div class="mb-3">
<label for="message" class="form-label">Сообщение</label>
<textarea class="form-control" name="message" id="message" rows="3"></textarea>
<div class="invalid-feedback"></div>
</div>
<div class="mb-3">
<input type="submit" class="btn btn-primary" name="feedback-form" value="Отправить">
</div>
</form>
2. Добавим в нужный ресурс или шаблон вызов сниппета AjaxForm
и скрипт:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
[[AjaxForm?
&form=`myFormTpl`
&formSelector=`feedback-form`
&emailTpl=`myEmailTpl`
&emailTo=`alexander@gmail.com`
&hooks=`email`
&successMessage=`Форма успешно отправлена!`
&validationErrorMessage=`В форме содержатся ошибки!`
&submitVar=`feedback-form`
&validate=`nospam:blank,
name:required,
email:email:required,
message:required:minLength=^20^`
]]
<script>
$(document).on('af_complete', function(event, response) {
const elForm = $(response.form);
elForm.find('.is-invalid').each(function(index, el) {
$(el).removeClass('is-invalid');
});
for (let key in response.data) {
const elInput = elForm.find(`[name=${key}]`);
elInput.addClass('is-invalid');
elInput.next('.invalid-feedback').text($(response.data[key]).text());
}
});
</script>
Свойство form
в вызове сниппета AjaxForm
указывает чанк, в котором содержится HTML форма. Остальные свойства данный сниппет просто передаёт FormIt
.
Скрипт необходим для установки не валидным полям класса is-invalid
и вставки сведений об ошибках в элементы .invalid-feedback
. Кроме этого JavaScript файлы, которые регистрирует AjaxForm во фронтенде, написаны с использованием библиотеки jQuery. Поэтому её нужно подключить.
Дополнительно
1. Редирект на другую страницу после успешной обработки формы.
Перенаправить пользователя на другую страницу после успешной отправки формы можно с помощью хука redirect
:
&hooks=`email,redirect`
&redirectTo=`7`
Указание ресурса, на который необходимо перенаправить пользователя осуществляется с помощью свойства redirectTo
. В данном примере пользователь будет перенаправлен на ресурс, который имеет в качестве id
значение 7
.
2. Сохранение данных формы в базу данных.
Сохранить отправленные формы в базу данных можно с помощью хука FormItSaveForm
:
&hooks=`email,FormItSaveForm`
&formName=`Форма обратной связи`
&formFields=`name,email,message`
&fieldNames=`name==Имя,email==Email,message==Сообщение`
Свойства:
formName
– название формы. По умолчанию:"form-{resourceid}"
;formFields
– список полей, которые следует сохранить. По умолчанию: все поля, включая кнопкуsubmit
;fieldNames
– позволяет задать отображение полей на форме в менеджере.
3. Добавление в форму заголовка и URL страницы
Добавить в форму дополнительные данные, например заголовок страницы и её URL, можно с помощью скрытых полей:
<input type="hidden" name="title" value="[[*pagetitle]]">
<input type="hidden" name="url" value="[[~[[*id]]? &scheme=`full`]]">
Для отправки этой информации на email
добавьте в шаблон письма:
<p>Страница, с которой отправлена форма: <a href="[[+url]]">[[+title]]</a></p>
4. Обработка полей select
Для обработки <select>
FormIt предоставляет фильтр вывода FormItIsSelected
. Он устанавливает атрибут selected
, если значение <option>
соответствует выбранной:
<div class="mb-3">
<label for="color" class="form-label">Цвет</label>
<select class="form-select[[!+fi.error.color:notempty=` is-invalid`]]" name="color" id="color" value="[[!+fi.color]]">
<option value="" selected disabled>Выберите цвет</option>
<option value="Красный" [[!+fi.color:FormItIsSelected=`Красный`]]>Красный</option>
<option value="Оранжевый" [[!+fi.color:FormItIsSelected=`Оранжевый`]]>Оранжевый</option>
<option value="Желтый" [[!+fi.color:FormItIsSelected=`Желтый`]]>Желтый</option>
</select>
<div class="invalid-feedback">[[!+fi.error.color]]</div>
</div>
5. Обработка чекбоксов и радиокнопок
FormIt для обработки type="checkbox"
и type="radio"
предоставляет фильтр FormItIsChecked
аналогичный FormItIsSelected
.
Это пример с чекбоксами:
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input [[!+fi.error.colors:notempty=` is-invalid`]]" name="colors[]" id="colors-red" value="Красный" [[!+fi.colors:FormItIsChecked=`Красный`]]>
<label class="form-check-label" for="colors-red">Красный</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input [[!+fi.error.colors:notempty=` is-invalid`]]" name="colors[]" id="colors-orange" value="Оранжевый" [[!+fi.colors:FormItIsChecked=`Оранжевый`]]>
<label class="form-check-label" for="colors-orange">Оранжевый</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input [[!+fi.error.colors:notempty=` is-invalid`]]" name="colors[]" id="colors-yellow" value="Желтый" [[!+fi.colors:FormItIsChecked=`Желтый`]]>
<label class="form-check-label" for="colors-yellow">Желтый</label>
</div>
<input type="hidden" class="[[!+fi.error.colors:notempty=` is-invalid`]]" name="colors[]" value="">
<div class="invalid-feedback">[[!+fi.error.colors]]</div>
</div>
Если colors
должно быть обязательным, то нужно добавить «скрытое» поле, как это показано в примере выше. После этого в свойство validate
добавить colors:required
:
[[!FormIt?
...
&validate=`...
colors:required`
]]
Добрый день.
Не могу разобраться, где допускаю ошибку.
Есть форма обратной связи с полем cost.
Есть вызов FormIt с валидацией для поля cost:
[[!FormIt?
&hooks=`spam,email,FormItSaveForm`
&validate=`cost:isBigEnough`
&emailTpl=`emailTpl`
&emailTo=`n.baravaya@gmail.com`
&emailSubject=`Заявка с сайта`
&emailFrom = `n.baravaya@gmail.com`
&formName = `Zayavka`
]]
Есть сниппет isBigEnough:
$value = (float)$value;
$success = $value > 1000;
if (!$success) {
$validator->addError($key,'Not big enough!');
}
return $success;
который как я понимаю, должен в случае, если в поле cost будет введено значение
<1000, вывести в value поля cost сообщение: Not big enough!
Есть соответственно input c именем cost в форме и плейсхолдер в чанке — emailTpl
Однако, по нажатию на submit форма прсто отправляется на почту, без проверки поля cost.
Почему такт происходит? В чем ошибка?
Здравствуйте.
Помогите пожалуйста советом, так как всё перерыл в сети информацию по данной теме. (На modx вообще скупая информация с интернете, в плане тонкостей и проблем) Помещаю этот код в шаблон, пробуя вызвать чанк через сниппет вышесказанный и он не появляется на странице. Хотя вызывая его напрямую он является на свет:
&snippet=`FormIt`
&form=`ajaxForm`
&emailTpl=`email_tpl`
&hooks=`email`
&emailSubject=`Lear Corporation`
&emailTo=`niceclient@yandex.ru`
&emailFrom=`tornado@kalugainfo.ru`
&validate=`name:minLenght=^3^,email:email:required,message:required`
&validationErrorMessage=`В форме содержатся ошибки!`
&successMessage=`Сообщение успешно отправлено`
]]
задан 17 фев 2018 в 12:21
AjaxForm это «обертка» для других сниппетов, в данном случае FormIt. Убедитесь что оба дополнения установлены, а чанк ajaxForm существует и содержит html форму.
Корректный вызов AjaxForm для работы с FormIt:
[[!AjaxForm?
&snippet=`FormIt`
&form=`ajaxForm`
&emailTpl=`email_tpl`
&hooks=`email`
&emailSubject=`Lear Corporation`
&emailTo=`niceclient@yandex.ru`
&emailFrom=`tornado@kalugainfo.ru`
&validate=`name:minLenght=^3^,email:email:required,message:required`
&validationErrorMessage=`В форме содержатся ошибки!`
&successMessage=`Сообщение успешно отправлено`
]]
ответ дан 21 фев 2018 в 20:13
Отредактировано: 14 Ноября 2019
AjaxForm это надстройка для компонента FormIt, которая позволяет отправлять результаты форм используя ajax (можно использовать не только FormIt, но и другие скрипты). Для перехода с FormIt на AjaxForm достаточно изменить запись вызова
[[!AjaxForm?
&snippet=`FormIt` // указываем сниппет который должен вызывать AjaxForm
&form=`tpl.form.feedback` // указываем шаблон формы
... // остальные строки вызова FormIt
]]
Этапы создания Ajax формы на сайте:
- Устанавливаем компоненты FormIt и AjaxForm.
- Создаем чанк с HTML формой и модификаторами.
- Размещаем вызов в соответствующем ресурсе или шаблоне.
Стандартная форма обратной связи
[[!AjaxForm?
&snippet=`FormIt`
&form=`tpl.form.feedback`
&emailTpl=`mailtpl.feedback`
&hooks=`email,spam,FormItSaveForm`
&spamCheckIp=`true`
&emailFrom=`info@domain.ru`
&emailSubject=`Письмо с сайта domain.ru`
&emailTo=`info@domain.ru`
&validate=`name:required,email:email:required,message:required`
&validationErrorMessage=`Не заполненны все необходимые поля`
&successMessage=`Сообщение успешно отправлено`
]]
// содержимое чанка tpl.form.feedback
<form action="" method="post">
<label for="name">Имя*</label>
<input id="name" name="name" value="[[!+fi.name]]">
<label for="email">Email*</label>
<input id="email" name="email" value="[[!+fi.email]]">
<label for="message">Сообщение*</label>
<textarea id="message" name="message" value="[[!+fi.message]]"></textarea>
<input class="btn gradient-border" type="submit" value="Отправить сообщение">
[[!+fi.validation_error_message:!empty=`
<div class="alert">
<p>Пожалуйста, исправьте следующие ошибки:</p>
<ul>
[[!+fi.error.name:!empty=`<li><a href="notes/web/back-end/modx/formit/#name">Поле «Имя» не заполнено</a></li>`]]
[[!+fi.error.email:!empty=`<li><a href="notes/web/back-end/modx/formit/#email">Поле «Email» не заполнено</a></li>`]]
</ul>
</div>`]]
</form>
// чанк mailtpl.feedback
<p>Имя: [[+name]]</p>
<p>Email: [[+email]]</p>
<p>Телефон: [[+phone]]</p>
<p>Сообщение: [[+message]]</p>
В AjaxForm есть дефолтный вид всплывающих окон об успешной отправке и ошибках, чтобы его изменить, надо указать собственные файлы в параметрах frontend_js и frontend_css.
Пример файла без jGrowl, со статичным сообщением во всплывающем окне с id massage
var AjaxForm = {
initialize: function (afConfig) {
if (!jQuery().ajaxForm) {
document.write('<script src="' + afConfig['assetsUrl'] + 'js/lib/jquery.form.min.js"></script>');
}
$(document).off('submit', afConfig['formSelector']).on('submit', afConfig['formSelector'], function (e) {
$(this).ajaxSubmit({
dataType: 'json',
data: {pageId: afConfig['pageId']},
url: afConfig['actionUrl'],
beforeSerialize: function (form) {
form.find(':submit').each(function () {
if (!form.find('input[type="hidden"][name="' + $(this).attr('name') + '"]').length) {
$(form).append(
$('<input type="hidden">').attr({
name: $(this).attr('name'),
value: $(this).attr('value')
})
);
}
})
},
beforeSubmit: function (fields, form) {
//noinspection JSUnresolvedVariable
if (typeof(afValidated) != 'undefined' && afValidated == false) {
return false;
}
form.find('.error').html('');
form.find('.error').removeClass('error');
form.find('input,textarea,select,button').attr('disabled', true);
return true;
},
success: function (response, status, xhr, form) {
form.find('input,textarea,select,button').attr('disabled', false);
response.form = form;
$(document).trigger('af_complete', response);
if (!response.success) {
if (response.data) {
var key, value, focused;
for (key in response.data) {
if (response.data.hasOwnProperty(key)) {
if (!focused) {
form.find('[name="' + key + '"]').focus();
focused = true;
}
value = response.data[key];
form.find('.error_' + key).html(value).addClass('error');
form.find('[name="' + key + '"]').addClass('error');
}
}
}
}
else {
form.find('.error').removeClass('error');
form[0].reset();
//noinspection JSUnresolvedVariable
if (typeof(grecaptcha) != 'undefined') {
//noinspection JSUnresolvedVariable
grecaptcha.reset();
}
$('.overlay').fadeIn('fast', function () {
$('#message').animate({
'top': '50%'
}, 500);
});
}
}
});
e.preventDefault();
return false;
});
$(document).on('keypress change', '.error', function () {
var key = $(this).attr('name');
$(this).removeClass('error');
$('.error_' + key).html('').removeClass('error');
});
$(document).on('reset', afConfig['formSelector'], function () {
$(this).find('.error').html('');
AjaxForm.Message.close();
});
}
};
Пример файла с редиректом после успешной отправки
var AjaxForm = {
initialize: function (afConfig) {
if (!jQuery().ajaxForm) {
document.write('<script src="' + afConfig['assetsUrl'] + 'js/lib/jquery.form.min.js"></script>');
}
if (!jQuery().jGrowl) {
document.write('<script src="' + afConfig['assetsUrl'] + 'js/lib/jquery.jgrowl.min.js"></script>');
}
$(document).ready(function () {
$.jGrowl.defaults.closerTemplate = '<div>[ ' + afConfig['closeMessage'] + ' ]</div>';
});
$(document).off('submit', afConfig['formSelector']).on('submit', afConfig['formSelector'], function (e) {
$(this).ajaxSubmit({
dataType: 'json',
data: {pageId: afConfig['pageId']},
url: afConfig['actionUrl'],
beforeSerialize: function (form) {
form.find(':submit').each(function () {
if (!form.find('input[type="hidden"][name="' + $(this).attr('name') + '"]').length) {
$(form).append(
$('<input type="hidden">').attr({
name: $(this).attr('name'),
value: $(this).attr('value')
})
);
}
})
},
beforeSubmit: function (fields, form) {
//noinspection JSUnresolvedVariable
if (typeof(afValidated) != 'undefined' && afValidated == false) {
return false;
}
form.find('.error').html('');
form.find('.error').removeClass('error');
form.find('input,textarea,select,button').attr('disabled', true);
return true;
},
success: function (response, status, xhr, form) {
form.find('input,textarea,select,button').attr('disabled', false);
response.form = form;
$(document).trigger('af_complete', response);
if (!response.success) {
AjaxForm.Message.error(response.message);
if (response.data) {
var key, value, focused;
for (key in response.data) {
if (response.data.hasOwnProperty(key)) {
if (!focused) {
form.find('[name="' + key + '"]').focus();
focused = true;
}
value = response.data[key];
form.find('.error_' + key).html(value).addClass('error');
form.find('[name="' + key + '"]').addClass('error');
}
}
}
}
else {
AjaxForm.Message.success(response.message);
form.find('.error').removeClass('error');
form[0].reset();
//noinspection JSUnresolvedVariable
if (typeof(grecaptcha) != 'undefined') {
//noinspection JSUnresolvedVariable
grecaptcha.reset();
}
//редиректим на страницу
document.location.href = "http://адрес/для/редиректа"
}
}
});
e.preventDefault();
return false;
});
$(document).on('keypress change', '.error', function () {
var key = $(this).attr('name');
$(this).removeClass('error');
$('.error_' + key).html('').removeClass('error');
});
$(document).on('reset', afConfig['formSelector'], function () {
$(this).find('.error').html('');
AjaxForm.Message.close();
});
}
};
//noinspection JSUnusedGlobalSymbols
AjaxForm.Message = {
success: function (message, sticky) {
if (message) {
if (!sticky) {
sticky = false;
}
$.jGrowl(message, {theme: 'af-message-success', sticky: sticky});
}
},
error: function (message, sticky) {
if (message) {
if (!sticky) {
sticky = false;
}
$.jGrowl(message, {theme: 'af-message-error', sticky: sticky});
}
},
info: function (message, sticky) {
if (message) {
if (!sticky) {
sticky = false;
}
$.jGrowl(message, {theme: 'af-message-info', sticky: sticky});
}
},
close: function () {
$.jGrowl('close');
},
};
Настройка целей для счетчиков
Отслеживать успешную отправку формы, без изменения кода компонента можно добавив перехватчик в сообщение об успешной отправке:
&successMessage=`Ваше письмо успешно отправлено <script>yaCounterXXXXXXXX.reachGoal('form');</script>`
Документация сниппета AjaxForm
AjaxForm
14 августа 2019, 07:00
Cниппет для отправки любых форм через ajax. По умолчанию рассчитан на работу с FormIt, но можно использовать и собственный сниппет.
- Регистрирует нужные скрипты на фронтенде: jQuery.Form и jQuery.jGrowl.
- Сохраняет в сессию
$scriptProperties
при вызове сниппета. - Выводит указанную форму, прописывая класс ajax_form и скрытый input для получения
$scriptProperties
. - Вешает обработчик на форму, чтобы она отправлялась через ajax.
- При отправке запускает указанный сниппет для обработки и возвращает ответ от него.
- Выводит сообщение об успехе, или ошибки, если есть.
Параметры сниппета
Имя | По умолчанию | Плейсхолдеры |
---|---|---|
&form | tpl.AjaxForm.example | Образец чанка с формой, которую нужно обработать. |
&snippet | FormIt | Сниппет для обработки формы. |
&frontend_css | [[+assetsUrl]]css/default.css | Стили оформления формы и полей с ошибками |
&frontend_js | [[+assetsUrl]]js/default.js | Javascript для отправки формы через ajax |
&actionUrl | [[+assetsUrl]]action.php | Адрес коннектора, на который отправляется форма |
Всё, что вы указываете AjaxForm, будет передано в вызываемый сниппет.
Обработка своим сниппетом
Вы можете использовать собственный сниппет, вместо FormIt, который будет делать что угодно (хоть создавать страницы на сайте).
Единственное требование — он обязательно должен возвращать JSON массив с ключами:
- status — 1 или 0, то есть успех или ошибка.
- message — сообщение о работе сниппета, выводится если status = 0.
- data — массив для полей с ошибками, в котором ключами является имя поля, а значением — сообщение об ошибке.
Для удобства работы в параметры сниппета передаётся переменная $AjaxForm
с классом компонента, чтобы вы могли вызывать из него методы error и success при выдаче ответа.
Простейший пример своего сниппета:
<?php
if (empty($_POST['name'])) {
return $AjaxForm->error('Ошибки в форме', array(
'name' => 'Вы не заполнили имя'
));
}
else {
return $AjaxForm->success('Форма прошла проверку');
}
Вызываем так:
[[!AjaxForm?
&snippet=`MySnippet`
&form=`tpl.AjaxForm.example`
]]
Этот сниппет ничего не делает, просто возвращает результат проверки имени.
Валидация формы
Сервер может вернуть ошибку отправки формы и массив полей, не прошедших проверку.
Этим полям автоматически будет добавлен CSS класс error
, который убирается при последующей отправке.
Так же вы можете запретить отправку формы, используя javascript переменную afValidated — если она объявлена и равна false
, то форма не будет отправлена.
Обратите внимание, что все проверки на javascript можно обойти, так что эту переменную стоит использовать только для удобства пользователей, а не для реальной проверки данных.
<script type="text/javascript">
$(document).on('submit', '.ajax_form', function() {
// Здесь любой код для проверки формы при отправке
// Я просто печатаю её в консоли бразуреа
console.log(this);
// Результатом работы будет выставление глобальной переменной
afValidated = false; // Или true, если валидация пройдена
});
</script>
[[!AjaxForm]]
Событие af_complete
При получении ответа от сервера вызывается событие af_complete, которое вы можете использовать для обновления содержимого страницы или другой операции javascript.
Вам просто нужно указать функцию, в которую будет передано событие javascript и объект с ответом от сервера. Обратите внимание, что внутри этого объекта есть и отправляющая форма.
$(document).on('af_complete', function(event, response) {
var form = response.form;
// Если у формы определённый id
if (form.attr('id') == 'my_form_3') {
// Скрываем её!
form.hide();
}
// Иначе печатаем в консоль весь ответ
else {
console.log(response)
}
});
redirect на другую страницу сайта, после успешной отправки формы?
Добавляем id к форме, если его нет и затем в js файл прописать вот такие строки
$(document).on('af_complete', function(event, response) {
var form = response.form;
if (form.attr('id') == 'значение id формы') {
window.location.href = "[[~id страницы]]"
}
});
Можно просто обернуть в <script>
выше приведенный код</script>
и подключить в шаблон с формой ближе к закрытию body.
Всплывающие сообщения
По умолчанию AjaxForm выводит сообщения об успешной отправке формы или о наличии ошибок.
Вы можете самостоятельно вызывать их для своих целей:
AjaxForm.Message.success('Зеленый popup');
AjaxForm.Message.error('Красный popup', 1);
AjaxForm.Message.info('Черный popup');
Вторым параметром можно указать «прилипающий» popup — его нужно будет закрыть вручную, бывает полезно для показа серьёзных ошибок.
То есть, просто вызвав сниппет на странице, вы получаете подключенный jQuery.jGrowl и можете показывать приятные всплывающие уведомления на javascript.
Примеры
Отправка email сообщения при помощи FormIt с требованием некоторых полей:
[[!AjaxForm?
&snippet=`FormIt`
&form=`tpl.AjaxForm.example`
&hooks=`email`
&emailSubject=`Тестовое сообщение`
&emailTo=`info@domain.com`
&validate=`name:required,email:required,message:required`
&validationErrorMessage=`В форме содержатся ошибки!`
&successMessage=`Сообщение успешно отправлено`
]]
Отладка
При возникновении любых проблем, в первую очередь проверяйте, отправляется ли форма без AjaxForm.
Помните, что AjaxForm — сниппет-обёртка, он не отправляет письма и не проводит проверку формы. Это делает ваш сниппет или FormIt.
Так же не забывайте заглядывать в консоль браузера на предмет ошибок javascript.
Если сервер выдаёт ошибку 500 при отправке, проверьте параметр register_globals у вашего PHP — он должен быть отключен.