Загрузка и отправка формы по AJAX на Drupal 7

в 18:48, , рубрики: ajax, drupal, php, метки: , ,

image Недавно мне потребовалось реализовать сабмит формы по AJAX. При этом форма должна загружаться в попапе. Казалось бы задача тривиальная, но оказалось что все же есть подводные камни.
Задача решается для Drupal 7. В качестве библиотеки для создания popup'ов используется fancybox.

Сперва нужно подключить необходимые библиотеки:

  $path = drupal_get_path('module', 'simple_ajax_popup');
  drupal_add_js($path . '/misc/fancybox/source/jquery.fancybox.pack.js');  
  drupal_add_css($path . '/misc/fancybox/source/jquery.fancybox.css');
  drupal_add_js($path . '/misc/simple_ajax_popup.js');
  drupal_add_js('misc/jquery.form.js');

Файл jquery.form.js подключается друпалом каждый раз, когда на странице присутствует форма. Этот файл необходим для отправки формы по AJAX. Поскольку в момент отрисовки страницы этой формы еще нет, то друпал не подключит этот файл и его нужно подключить вручную.

Затем в хуке меню нужно добавить новый итем, который и будет загружать форму:

  $items['simple-popup/form'] = array(
    'page callback' => 'simple_ajax_popup',
    'access callback' => TRUE,
  );

Колбеком будет являться функция, которая будет возвращать либо саму форму либо результаты сабмита.

Для того чтобы вызывать колбек, в любом удобном месте помещаем ссылку:

print l(
  'AJAX form',
  'simple-popup/form',
  array(
    'attributes' => array('class' => array('fancybox', 'fancybox.ajax')),
  )
);

Важно не забыть подключить библиотеку друпала для работы с AJAX

drupal_add_library('system', 'drupal.ajax');

А также навесить на событие fancybox'а afterShow функцию для обработки формы на javascript:

function simpleAjaxPopupFormProcess() {
  Drupal.attachBehaviors('#simple_ajax_popup_form');
  jQuery('#simple_ajax_popup_form').ajaxForm();
}
 

В самом колбеке разместим простой код, который будет проверять — отправлен ли POST запрос. Если нет то функция вернет форму, а если POST запрос был отправлен то обработает данные.

function simple_ajax_popup() {
  // POST is empty - load popup.
  if (empty($_POST)) {
    $form = drupal_render(drupal_get_form('simple_ajax_popup_form'));
    print $form;
    exit();
  }
  // If we have POST - process fields values.
  else {
    // Validation.
    $errors = simple_ajax_popup_form_validate($_POST);
    // Show errors.
    if ($errors) {
 
      $commands = array();
      $commands[] = ajax_command_replace(
        '#popup-info-box',
        $errors
      );
      ajax_deliver(array('#type' => 'ajax', '#commands' => $commands));
    }
    // Add message.
    else {
      watchdog('ajax message', $_POST['message']);
      $commands = array();
      $commands[] = ajax_command_replace(
        '#simple-ajax-popup-form',
        '<div class="messages status">Сообщение добавлено в системный журнал.</div>'
      );
      ajax_deliver(array('#type' => 'ajax', '#commands' => $commands));
    }
  }
}

Для ответа используется функция ajax_deliver. Функция ajax_command_replace позволяет добавить в ответ AJAX запроса команду, заменяющую контент по указанному врапперу.

Таким образом можно показать сообщение об ошибке:

Загрузка и отправка формы по AJAX на Drupal 7

Или сообщение об успешной отправке:

Загрузка и отправка формы по AJAX на Drupal 7

В данном случае форма просто добавляет сообщение в watchdog.

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

  $form['form_wrapper']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Отправить.'),
    '#attributes' => array('class' => array('use-ajax-submit')),
  );

Полный код примера можно скачать тут

Реальный проект где используется такая отправка форм через popup — модуль comment abuse.

Автор: IlyinEugene

* - обязательные к заполнению поля