Изменить существующую форму

12

Мы только начинали с Drupal 8 и очень быстро столкнулись с нашей первой проблемой.

Как мне изменить существующую форму в Drupal 8?

Нам нужно изменить метод сохранения для формы узла, чтобы сделать перенаправление на другую страницу. Мы хотим изменить форму узла, чтобы она стала чем-то вроде многошаговой формы. После того, как пользователь создает новый контент, он перенаправляется в новую форму (мы создали), чтобы получить больше информации.

Мы решили нашу проблему реализации hook_entity_type_alter().

function mymodule_entity_type_alter(&$entity_info) {
  $handlers = $entity_info['node']->get('handlers');
  $handlers['form']['default'] =    'Drupal\mymodule\Form\MyExtendedNodeForm';
  $handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
  $entity_info['node']->set('handlers', $handlers);
}

Затем мы создали новый класс формы, который расширяет форму узла и изменяет метод сохранения.

class MyExtendedNodeForm extends NodeForm {

    public function save(array $form, FormStateInterface $form_state) {
      parent::save($form, $form_state);
      $node = $this->entity;
      $form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
  }

}

Это отлично работает, но хорошо ли это? Если другой модуль делает то же самое, наш код больше не выполняется.

Йенс Степь
источник
2
Drupal 8 все еще поддерживает hook_form_alter(). Если вам просто нужно перенаправить форму, достаточно добавить обработчик отправки формы, который выполняет перенаправление.
kiamlaluno
@kiamlaluno Это должен быть ответ, я думаю :)
Бердир
Боюсь, это само по себе не очень поможет: мои знания о Drupal 8 довольно ограничены. Плюс, ОП должен прояснить, что на save()самом деле означает «изменить метод». Означает ли это изменение способа сохранения данных или просто перенаправление? В первом случае ответ более сложный.
kiamlaluno
@kiamlaluno Спасибо за ответ. В этом случае нам нужно выполнить перенаправление только после save (), чтобы ваш ответ работал. Но меня также интересовало, как правильно изменить Drupal 8 для других вещей в форме. Например, измените способ его сохранения или добавьте поля в форму ... и т. Д.
Йенс

Ответы:

4

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

<?php

/**
 * @file
 * This is my module.
 */

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Implements hook_form_alter().
 */
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['actions']['submit']['#submit'][] = '_MODULE_goto';
  }
}

/**
 * Make the form go to route.id.
 */
function _MODULE_goto($form, FormStateInterface $form_state) {
  $form_state->setRedirect('route.id');
}

Я все еще очень заинтересован в том, чтобы сделать это по-другому, мой модуль выглядел так чисто без файла .module :).

Dagomar
источник
3

Я использую Drupal 8.1.1 и пытался перенаправить пользователей после того, как они изменили свою учетную запись, т.е. нажав кнопку Сохранить на странице / user / edit. Я изначально попробовал это:

/**
 * Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['#submit'][] = '_MODULE_goto';
  }
}

Хотя это работает для user_login_form, это не будет работать для user_form. Для user_formменя было использовать

$form['actions']['submit']['#submit'][] = '_MODULE_goto';

Я надеюсь, что это помогает другим, кто сталкивается с той же проблемой!

Эрик С.
источник
1

Ну, я хотел изменить site_information_settingsформу, чтобы добавить несколько полей.

Как и у вас, у меня был выбор между

  • hook_form_alter(или hook_form_FORM_ID_alter)
  • расширить исходный класс формы

Хотел сделать несколько ООП, поэтому я начал писать услугу подписчика маршрута, изменяя атрибут system.site_information_settingsмаршрута _form.

Затем в моем новом классе SiteInformationForm, после добавления полей и их валидаторов и расширения функции отправки, я чувствовал себя точно так же, как и вы ... Теперь, что, если другой модуль также переписывает маршрут формы, чтобы использовать свой собственный класс?

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

hook_form_alter/, hook_form_FORM_ID_alterкажется, лучший способ изменить существующую форму.

Macsim
источник
0

Похоже, что вы хотите сделать, это не на самом деле изменить метод сохранения, но изменить перенаправление при сохранении узла.

В этой ситуации hook_form_alterбыло бы неплохо сделать Drupal 7 вместе с пользовательским обработчиком отправки (в форме или на кнопке, в зависимости от формы и требований).

То, что вы описываете в вопросе, также работает, но я бы не стал перезаписывать базовый класс, если только я действительно не хочу что-то менять в классе.

В любом случае метод save используется только как обработчик отправки, поэтому нет смысла перезаписывать его, просто добавив перенаправление.

googletorp
источник
0

Я думаю, что лучший способ по-прежнему использовать один из хуков из семейства form_alter, прикрепить обработчик отправки и в этом установить ваш редирект.

Содействовать расширению базовых классов, чтобы сделать это волосатым, на мой взгляд. Тем более что ни одна функция не меняется, только перенаправление.

Kevin
источник
0

Вы можете создать новый EventSubscriber, который прослушивает событие KernelEvents :: REQUEST, а затем реагирует, когда вы отправляете форму узла, что-то вроде этого

В любом случае способ hook_form_alter работает нормально.

ruloweb
источник
0

Что я нашел до сих пор: Реализация перехватчика формы и попытка изменить обработчики проверки / отправки в самой перехватчике формы работает, только если вы измените обработчики $ form ['# validate] / $ form [#submit']. (вызов функции form_state для этого не будет работать в самой форме Alter Hook)

Но когда вы попробуете это внутри обработчика проверки, это будет работать:

// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();

// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
  unset($submit_handlers[$key_core_submit]);
  // Add your own submit handler.
  array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);

Это потому, что форма теперь построена полностью, а не случай в самой форме.

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

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

Я все еще ищу лучший способ, мне просто нужно заменить обработчики проверки / отправки для формы регистрации пользователя. Но могут существовать и другие модули, которые нарушают реализацию моих модулей. Так что мой модуль должен быть в состоянии проверить это, и это возможно таким образом. Я действительно задаюсь вопросом, существует ли какая-либо форма сущности после функции сборки, чтобы осуществить это. (то, что запускается, когда форма была заполнена и собирается быть доставленной) (это не слишком сложно для этого простого случая)

Обход перенаправления метода save () невозможен, но сброс сохранения () осуществляется таким образом (+ реализуйте свой собственный). Правда, класс лучше и предлагает более легкий доступ к объектам и т. Д., Но переопределение базового класса действительно приводит к проблемам, когда другие модули хотят использовать их. Это не тот случай, если вы используете этот код.

Роб С
источник
0

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

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
Иоанна Тодеа
источник