Змініть існуючу форму


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 Ось так я думаю, на що я думаю:
Бердір

@Berdir Це одне не було б дуже корисно, я боюся: мої знання про Drupal 8 досить обмежені. Плюс до цього, ОП повинна чітко пояснити, що save()насправді означає "зміна методу". Чи означає це змінити спосіб збереження даних або просто зробити переадресацію? У першому випадку відповідь складніша.
kiamlaluno

@kiamlaluno Thx для відповіді. У цьому випадку нам потрібно зробити переадресацію лише після save (), щоб відповідь мала спрацювати. Але мене також цікавило, як змінити інші речі у формі правильним способом Drupal 8. Наприклад, змінити спосіб його збереження або додати поля до форми .. тощо.
Jens Steppe

Відповіді:


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 :).


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)
  • розширити початковий клас форми

Я хотів зробити деякий OOP, тому я почав писати послугу абонента маршруту, змінюючи атрибут system.site_information_settingsмаршруту _form.

Потім у моєму новому класі, що розширює SiteInformationForm, після додавання полів та їх валідаторів та розширення функції подання, я почував себе точно так само, як і ви ... Тепер що робити, якщо інший модуль переписує маршрут форми, а також використовувати власний клас?

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

hook_form_alter/ hook_form_FORM_ID_alterздається, найкращий спосіб змінити існуючу форму.


0

Схоже, що ви хочете зробити, це насправді не для зміни методу збереження, а для зміни переспрямування, коли вузол збережений.

У цій ситуації hook_form_alterхорошим рішенням було б зробити так, як Drupal 7, а також спеціальний обробник подачі (на формі або кнопці, залежно від форми та вимоги).

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

Метод збереження використовується щойно використаний як обробник подачі, тому не має сенсу перезаписувати лише те, щоб додати переадресацію.


0

Я вважаю, що кращим методом є все-таки використовувати один з гачків із сімейства form_alter, приєднати обробник подання та всередині цього встановити переспрямування.

На мою думку, сприяти розширенню базових класів, щоб це зробити, є волохатим. Тим більше, що жодна функція не змінюється, просто перенаправляється.


0

Ви можете створити новий EventSubscriber , який прослуховує подія KernelEvents :: REQUEST, а потім реагувати , коли ви відправляєте форму вузла, що - щось на зразок цього

У будь-якому випадку гак_форма_алтер добре працює.


0

Що я зараз знайшов: реалізація гака зміни форми та спробу змінити валідацію / подачу обробників у формі змінити гак само працює, якщо ви зміните обробники $ form ['# validate] / $ form [#submit']. (виклик функцій form_state для цієї роботи в формі змінити сам гак)

Але коли ви спробуєте це все в обробці валідації, воно, як правило, працює:

// 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');
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.