Как я могу реализовать отправку формы AJAX?


14

Моя задача - отправить контактную форму через AJAX, а затем показать «Спасибо за отправку!» сообщение, загруженное в том месте, где была форма. Поэтому мне нужно изменить существующую контактную форму.

Я нашел несколько примеров, как проверять поля формы с помощью AJAX в D8, но я не могу найти ни одного примера, как реализовать отправку формы ajax и загрузить некоторое содержимое через AJAX.

Как я могу реализовать свою задачу? Как мне изменить форму контакта, чтобы добавить необходимые функции?


Для тех, кто попадает сюда с общим вопросом о форме: модуль Webform позволяет создавать форму так, как вы хотите, и разрешать отправлять результаты через ajax.
Флориан Мюллер

Ответы:


26

При работе с ajax в формах вы должны иметь в виду следующее:

  • узнайте, перестраиваете ли вы всю форму или только ее часть, и оберните форму соответствующим образом элементом div с атрибутом ID, который вы будете использовать в определении #ajax для запускающего элемента как «обертка». Используйте атрибуты #prefix и #suffix для этого ( $form['#prefix'] = '<div id="myform-ajax-wrapper">'; $form['#suffix'] = '</div>';). Также имейте в виду, что если у вас есть пользовательский шаблон для вашей формы, чтобы НЕ отображать префикс и суффикс в этом случае ( {{ form|without('#prefix', '#suffix') }}), в противном случае они будут отображаться дважды - вашим шаблоном, а также оболочкой темы формы. Вы не можете предотвратить это, установив #theme_wrappers в пустой массив, поскольку шаблон формы содержит фактический HTML-элемент формы.

  • в вашем обработчике отправки ajax верните всю форму или ее часть, которую вы завернули и хотите восстановить ( return $formили return $form['myelement']). Вы можете дополнительно использовать команды ajax вместо простого возврата структуры формы, но это более сложный процесс.

  • хранить каждое значение в хранилище состояния формы, пока вы не отправите форму. Сделайте это в обработчике отправки ( $form_state->set('somevalue', $form_state->getValue('somevalue'))) и всегда вызывайте, $form_state->setRebuild()если вы не выполняете окончательную отправку формы. Я предпочитаю иметь собственные обработчики отправки, но с большей логикой в ​​основном обработчике отправки тоже все в порядке.

  • Всегда используйте #nameатрибут на кнопке, которая выполняет отправку, и если у вас есть только один обработчик отправки формы, используйте, $for_state->getTriggeringElement()['#name']чтобы определить, какой элемент отправил форму.

  • если вы используете 'trigger_as' в определении #ajax, если вы хотите отправить форму с элементом select, например, всегда используйте такое же определение #ajax, как и для кнопки. По моему опыту это требуется - хотя и не указано в документации.

  • Использование #limit_validation_errorsможет иногда быть очень сложным, и выяснение того, почему форма не работает, может занять довольно много времени, поэтому используйте его осторожно (это хорошо для изоляции ошибок формы только на элементе (элементах), которые вы фактически перестраиваете, чтобы ваш код не влияет на другие части формы).

  • всегда используйте кнопки для отправки формы, и если вы хотите, чтобы что-то необычное, например select было инициирующим элементом, используйте опцию 'trigger_as' в конфигурации #ajax и скрывайте реальную кнопку с классом 'js-hide' для хорошего пользовательского интерфейса.

  • в определении формы получите значения по умолчанию из хранилища состояния формы, если они существуют, или назначьте их в хранилище, если их нет. В противном случае форма не будет работать должным образом.

  • не используйте $ this или что-либо еще, к чему у вас нет внешнего доступа, иначе это сломает Ajax. всегда используйте статические обработчики ajax.

  • при окончательной отправке формы, в зависимости от того, что у вас (не) есть собственный обработчик отправки формы для ajax, отключите перестройку формы с помощью вызова $form_state->setRebuild(FALSE).

  • Вы можете использовать сокращенные вызовы :: в элементе отправки ajax ( $element['#ajax']['callback'] = '::ajaxFormRebuild';и $element['#submit'] = [['::ajaxFormSubmitHandler'];).

  • обратный вызов ajax предназначен только для возврата перестроенной формы или команд ajax. Никогда не возвращайте измененную форму (т.е. не изменяйте массив форм в этом обратном вызове).


Отличный контрольный список, если у вас есть проблемы с ajax в drupal 8! (Я не понимаю первый пункт, почему НЕ рендерит div ajax wrap?)
4k4

Я точно не помню, но думаю, что это как-то связано с #theme, #theme_wrappers и обработкой атрибутов #prefix и #suffix в рендере. Я думаю, что у вас получится обертка внутри элемента <form>. Это, конечно, применимо, только если вы перестраиваете всю форму, а не только какой-то элемент.

Спасибо, но где я могу найти простой пример отправки AJAX?
Сергей Кравченко


@IvanJaros, спасибо за ответ. Знаете ли вы, как очистить значения формы после отправки ajax?
Милковский

1

Чтобы добавить к этому контрольному списку, если вы отображаете форму в модальном окне, есть вероятность, что сообщения об ошибках не будут отображаться. Как сказал Иван Ярош, вы должны убедиться, что форма имеет обертку:

$form['#prefix'] = '<div id="my-form-wrapper-id">';
$form['#suffix'] = '</div>';

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

$form['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Save Changes'),
    '#attributes' => [
        'class' => [
            'btn',
            'btn-md',
            'btn-primary',
            'use-ajax-submit'
        ]
    ],
    '#ajax' => [
        'wrapper' => 'my-form-wrapper-id',
    ]
];

1

Я использую модуль Contact ajax . Еще несколько подробностей об этом (со страницы проекта):

Contact Ajax реализует представление ajax для формы контактов в Drupal 8.

Как это устроено

После включения модуля на каждой контактной форме будет отображаться флажок «Использовать ajax». Когда этот флажок установлен, форма контакта покажет вам другую опцию «Тип подтверждения» с этими опциями:

  • Загрузить форму: отправит форму без перезагрузки страницы.
  • Загрузить из пользовательского сообщения: загрузить пользовательский текст.
  • Загрузить из узла: загрузить узел после отправки формы.

Этот модуль может помочь вам, если:

  • вам нужно настроить подтверждающее сообщение
  • Вам необходимо отправить контактную форму без перезагрузки страницы.
  • Вы хотите загрузить пользовательский текст или другой узел после отправки формы.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.