В форме содержатся ошибки modx

Здравствуйте друзья!
Попросили подправить форму обратной связи, не отправляет письма.
Вызывается ошибка «Форма содержит ошибки» и красным подсвечивается форма с Почтой, типа адрес почты не правильный или отсутствует…

Форма выводится двумя дополнениями 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 для MODX

Пример простой формы обратной связи на FormIt

В этом примере создадим простую HTML форму с использованием Bootstrap 5. Она будет состоять из 3 полей: имя, email и сообщение. FormIt будет выполнять валидацию формы и отправлять сообщение с данными, которые ввел пользователь, на email.

Вид формы обратной связи на FormIt для MODX сайта

Вызов сниппета 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]]

Отображение ошибок валидации формы на FormIt для MODX сайта

3. Выполнение хуков. После успешной валидации будут последовательно друг за другом выполнены скрипты, указанные в hooks.

В приведённом примере мы используем в hooks только один скрипт: email. Он отправит форму на email. Шаблон для этого письма он возьмёт из чанка, заданного в emailTpl. А отправит он письмо на email, указанный в свойстве emailTo.

Сообщение отправленное на email с использованием FormIt для MODX сайта

4. Вывод сообщения об успехе. После успешного завершения хука email будет выведено в плейсхолдер fi.successMessage сообщение, указанное в свойстве successMessage.

Сообщение об успешной отправки формы на FormIt для MODX сайта

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 работа с формой будет осуществляться следующим образом:

  1. вывод HTML формы будет осуществляться из чанка, который передан AjaxForm в свойстве form;
  2. отправка форма выполняется через AJAX, для этого сниппет AjaxForm регистрирует на фронтенде нужные скрипты;
  3. на сервере запускает сниппет FormIt и передаёт ему данные формы;
  4. после получения ответа от FormIt передаёт его браузеру, который выводится пользователю на страницу с использованием JavaScript.

Перед тем как начать переделывать форму проверим установлено ли у нас расширение AjaxForm.

Установка пакета AjaxForm для MODX

Ход работы:

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==Сообщение`

Диалоговое окно для просмотра всех отправленных форм в админке MODX

Свойства:

  • 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>

Обработка поля формы select с помощью FormIt для сайта на MODX

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`
]]

Обработка checkbox полей формы с помощью FormIt для сайта на MODX

Добрый день.

Не могу разобраться, где допускаю ошибку.
Есть форма обратной связи с полем 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

Nice's user avatar

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

Neonich's user avatar

Отредактировано: 14 Ноября 2019

AjaxForm это надстройка для компонента FormIt, которая позволяет отправлять результаты форм используя ajax (можно использовать не только FormIt, но и другие скрипты). Для перехода с FormIt на AjaxForm достаточно изменить запись вызова 

[[!AjaxForm?
   &snippet=`FormIt` // указываем сниппет который должен вызывать AjaxForm
   &form=`tpl.form.feedback` // указываем шаблон формы
   ... // остальные строки вызова FormIt
]]

Этапы создания Ajax формы на сайте:

  1. Устанавливаем компоненты FormIt и AjaxForm.
  2. Создаем чанк с HTML формой и модификаторами.
  3. Размещаем вызов в соответствующем ресурсе или шаблоне.

Стандартная форма обратной связи

[[!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 — он должен быть отключен.

Возможно, вам также будет интересно:

  • В фольксваген поло загорелась ошибка двигателя
  • В фифе черный экран ошибки в фифа
  • В фифе 13 не было ошибки
  • В фифа 19 вылетает ошибка директ
  • В упд не указано платежное поручение является ошибкой

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии