Статьи

Использование форм Ajax в Drupal 8

В этой статье я собираюсь показать вам чистый способ использования Drupal 8 Ajax API без написания одной строки кода JavaScript. С этой целью мы вернемся к первой пользовательской форме, которую мы создали для Drupal 8 в предыдущей статье, и изменим ее поведение, чтобы сделать ее более удобной для пользователя.

Логотип Drupal 8

Обновленную версию этой формы можно найти в этом хранилище под именем DemoFormdemo Код, который мы пишем в этой статье, также можно найти там, но в отдельной ветке под названием ajax Я рекомендую вам клонировать репозиторий и установить модуль в вашей среде разработки, если вы хотите следовать.

DemoForm

Несмотря на плохое название, DemoForm Конечно, он фокусируется на основах и не имеет ничего захватывающего.

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

В этой статье мы переместим логику проверки электронной почты в обратный вызов Ajax, чтобы после того, как пользователь закончил вводить адрес электронной почты, проверка запускалась автоматически и печаталось сообщение без отправки формы. Опять же, в этом поведении нет ничего впечатляющего, и вы увидите его довольно часто в диких формах (обычно для проверки имен пользователей). Но это хорошее упражнение для просмотра Ajax в Drupal 8.

Аякс форма

Первое, что нам нужно сделать, это переместить логику проверки электронной почты из общего validateForm()

 /**
 * Validates that the email field is correct.
 */
protected function validateEmail(array &$form, FormStateInterface $form_state) {
  if (substr($form_state->getValue('email'), -4) !== '.com') {
    return FALSE;
  }
  return TRUE;
}

Как вы можете заметить, мы также немного изменили логику, чтобы адрес электронной почты заканчивался на .com

Затем мы можем обратиться к этой логике из основного метода проверки, чтобы убедиться, что наше существующее поведение все еще работает:

 /**
 * {@inheritdoc}
 */
public function validateForm(array &$form, FormStateInterface $form_state) {
  // Validate email.
  if (!$this->validateEmail($form, $form_state)) {
    $form_state->setErrorByName('email', $this->t('This is not a .com email address.'));
  }
}

Таким образом, даже если наша форма будет каким-либо образом отправлена ​​(программно или иным образом), проверка все равно будет выполнена.

Далее нам нужно обратиться к нашему определению формы, в частности к полю электронной почты, и заставить его запускать запросы Ajax на основе взаимодействия с пользователем. Это будет действие пользователя, меняющего значение поля и удаляющего с него фокус:

 $form['email'] = array(
  '#type' => 'email',
  '#title' => $this->t('Your .com email address.'),
  '#default_value' => $config->get('demo.email_address'),
  '#ajax' => [
    'callback' => array($this, 'validateEmailAjax'),
    'event' => 'change',
    'progress' => array(
      'type' => 'throbber',
      'message' => t('Verifying email...'),
    ),
  ],
  '#suffix' => '<span class="email-valid-message"></span>'
);

Что мы сделали здесь, это добавили ключ #ajax Кроме того, мы добавили небольшую разметку после элемента формы в качестве оболочки для короткого сообщения о достоверности электронного письма.

Обратный вызов внутри массива #ajaxvalidateEmailAjax()eventсобытия изменения jQuery. В качестве альтернативы, вы также можете указать ключ пути вместо обратного вызова, но в нашем случае это будет означать необходимость установки маршрута и контроллера, который кажется избыточным. И нам не нужен ключ- wrapper Для этого мы будем использовать команды Ajax.

Чтобы узнать больше обо всем этом, я советую вам посетить страницу API Ajax или запись API формы для Ajax. Есть несколько других опций, которые вы можете использовать для дальнейшей настройки поведения Ajax ваших элементов формы.

Теперь пришло время написать метод обратного вызова внутри нашего класса формы. Он получает массив $form$form_state

 /**
 * Ajax callback to validate the email field.
 */
public function validateEmailAjax(array &$form, FormStateInterface $form_state) {
  $valid = $this->validateEmail($form, $form_state);
  $response = new AjaxResponse();
  if ($valid) {
    $css = ['border' => '1px solid green'];
    $message = $this->t('Email ok.');
  }
  else {
    $css = ['border' => '1px solid red'];
    $message = $this->t('Email not valid.');
  }
  $response->addCommand(new CssCommand('#edit-email', $css));
  $response->addCommand(new HtmlCommand('.email-valid-message', $message));
  return $response;
}

Проще говоря, в этом методе мы выполняем проверку и возвращаем ответ Ajax с несколькими командами, которые отличаются в зависимости от результата проверки. С помощью CssCommand мы применяем некоторые CSS непосредственно к элементу формы электронной почты, в то время как с помощью HtmlCommand мы заменяем содержимое указанного селектора (помните суффикс из нашего элемента формы?).

Эти команды в значительной степени соответствуют функциям jQuery, поэтому их довольно легко понять. Вы можете найти список всех доступных команд на этой странице . И так как мы используем три новых класса внутри этого метода, мы должны помнить, что также использовать их в верхней части:

 use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\HtmlCommand;

И это в значительной степени это. Если вы очистите кеш и перезагрузите свою форму, ввод в поле электронной почты и удаление фокуса вызовет обратный вызов для проверки адреса электронной почты. Вы заметите маленький значок пульсирующего там (который можно изменить в определении) и короткое сообщение, которое мы определили. Правильный адрес электронной почты должен выделить поле зеленым цветом и напечатать сообщение OK, в то время как красный цвет используется с противоположным сообщением.

Если бы мы указали wrapper Таким образом, у вас есть возможность выбора между возвратом контента или командами Ajax, но я рекомендую последние для большинства случаев, поскольку они предлагают более гибкое (и согласованное) поведение.

Вывод

В этой статье мы увидели пример использования Ajax для улучшения нашей формы и повышения ее удобства для конечных пользователей. И мы написали ровно ноль строк javascript для достижения этой цели.

В нашем случае это действительно вопрос предпочтения или фантазии . Но если вы имеете дело с формой из 20 полей, которая имеет валидацию по нескольким полям, подобным этой, использование Ajax действительно имеет смысл. Это не раздражает пользователей от необходимости отправлять форму только для того, чтобы понять, что их ввод неверен.

Хотя формы — это основная область, в которой вы увидите Ajax в Drupal 8, есть пара других способов использовать его без написания JavaScript.

Один хороший способ — добавить класс use-ajax Это заставит Drupal делать Ajax-запрос к URL-адресу в атрибуте href Из обратного вызова вы можете возвращать команды Ajax и выполнять различные действия по мере необходимости. Но имейте в виду, что jQuery и другие базовые сценарии загружаются не на всех страницах для анонимных пользователей (следовательно, Ajax будет постепенно переходить к обычному поведению ссылок). Поэтому убедитесь, что вы включили эти сценарии для анонимных пользователей, если вам нужно такое поведение.