Drupal 7: отправка Webform через Ajax

На одном из проектов на Drupal 7 встала задача отправлять форму без перезагрузки страницы с уведомлением через модальное окно с подключенной Google Captcha, да ещё и кастомизированной темизацией. В статье буду приводить полученный код, и ссылки, которыми воспользовался в процессе.

Первая страница с которой началось моё изучение данной задачи это статья xandeadx:
Отправить Webform-у с помощью AJAX, в результате чего в своём кастомном модуле я реализовал следующие хуки:

    /**
    * Implements hook_form_FORM_ID_alter(): webform_client_form_17.
    */
    function custom_form_webform_client_form_17_alter(&$form, &$form_state) {

        $form['#attributes']['class'][] = 'support-form'; // добавляем класс формы
        $form['actions']['submit']['#attributes']['class'] = ['theme-btn'];

        // здесь всё, что касается ajax-а
        $form['actions']['submit']['#ajax'] = array(
            'callback' => 'custom_form_webform_client_form_ajax_submit',
            'wrapper' => $form['#id'],
        );
        $form['#attached']['js'][] = drupal_get_path("module", "custom")."/js/custom.js" ;
        //$form['actions']['submit']['#attributes']['class'][] = '';

        // Удаляем #pre_render, иначе не будет работать ajax
        unset($form['actions']['submit']['#pre_render']);
    }

Приведённый ваше код добавлял ajax-обработчик для кнопки submit-а и в качестве обработчика указывал функцию custom_form_webform_client_form_ajax_submit. Также в папку с кастомным модулем мы добаляем файл custom.js. В данном обработчике в случае ошибок мы возвращаем саму форму, а в случае успешной отправки формы мы выполняем опять же через ajax кастомную функцию responseForm, которая очищает поля и показывает модальное окно с сообщением об успешной или неуспешной отправки формы. Код функции реализован в подключенном файле custom.js.

Код кастомной функции:

    (function($) {
        /**
        * Special Effects AJAX framework command.
        */
        Drupal.ajax.prototype.commands.responseForm =  function(ajax, response, status) {
            if (status == 'success'){
                $('button.success').click();
                $("#webform-client-form-17 input[type='text'], #webform-client-form-17 textarea").val('');
                $("#webform-client-form-17 div.error").hide();
                $("#webform-client-form-17 input.error").removeClass('error');
            } else{
                $('button.error').click();
            }
        }

    }(jQuery));

Данный код $('button.success').click(); показывает модальное окно с сообщением о статусе отправленного сообщения, используя Bootstrap API.
HTML код:

Собственно после этого всё заработало!

Но у этого метода правда обнаружился недостаток один. Если форма отправляется с ошибками, то при повторной отправке в случае правильного заполнения форма не обнуляется. Поэтому функцию custom_form_webform_client_form_ajax_submit нужно немного переделать:

        /**
         * Ajax submit.
         */
        function custom_form_webform_client_form_ajax_submit($form, &$form_state) {
            if (form_get_errors()) {
                return $form;
            }
            else {
                // Выводим сообщеньку, если нужно
                drupal_set_message(t('Your message has been successfully sent! Thank you!'));

                // Смотрим кеш чистой формы
                $form = form_get_cache($form_state['input']['form_build_id'], $form_state);

                // Сбрасываем заполненные значения
                $form_state['input'] = array();

                // Грузим и возвращаем форму
                return form_builder($form['#form_id'], $form, $form_state);
            }
        }
    

Также нужно обратить внимание на следующий момент. После выполнения AJAX-запроса может потребоваться заново задать те или иные настройки с помощью различных JS-скриптов. Например, маска для ввода телефона в полях форм, установленная с помощью плагина jquery.maskedinput.min.js слетает. Восстановить это можно следующим образом.

    $(document).ajaxStop(function() {
        jQuery("input[name='submitted[phone]']").mask("+7(999) 999-9999");
    });

В этом случае форма корректно обнуляется и отправляется уже с нужным сообщением.

Ссылки которые оказали мне неоценимую помощь в понимании этого:
http://xandeadx.ru/blog/drupal/492
http://xandeadx.ru/blog/drupal/378
http://www.maged.me/blog/drupal-7-execute-javascript-code-after-ajax-call https://blogpost.pp.ua/drupal/118
http://drupalace.ru/lesson/zastavlyaem-lyubuyu-formu-vypolnyatsya-cherez-ajax-v-drupal-7

Тэги:

Тэг в списке: