修改现有表格


12

我们刚从Drupal 8开始,很快就遇到了第一个问题。

我应该如何更改Drupal 8中的现有表格?

我们需要更改节点表单的save方法以重定向到另一个页面。我们希望将节点形式更改为类似于多步形式的形式。用户创建新内容后,他们将被重定向到新表单(我们创建)以获取更多信息。

我们解决了实施中的问题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);
}

然后,我们创建了一个新的表单类,该类扩展了节点表单并更改了save方法。

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

@Berdir恐怕这并不会带来太大帮助,我担心:我对Drupal 8的了解非常有限。另外,OP应该明确“更改save()方法”的实际含义。这是否意味着更改数据保存方式,还是只是重定向?在第一种情况下,答案更为复杂。
kiamlaluno

@kiamlaluno Thx的答案。在这种情况下,我们只需要在save()之后进行重定向,这样您的答案就可以了。但是我也对如何以正确的Drupal 8方式更改表单中的其他内容感兴趣。例如改变它是如何保存,或将字段添加到窗体。等等。
延斯草原

Answers:


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页面上的Save按钮。我最初尝试这样做:

/**
 * 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,在添加了字段及其验证器并扩展了Submit函数之后,我的感觉与您完全相同... 现在,如果另一个模块也重写表单的路由以使用其自己的类怎么办?

回到开始时,我在两个选项之间选择。似乎我选错了一个。

hook_form_alter/ hook_form_FORM_ID_alter似乎是更改现有表格的最佳方法。


0

看起来就像您要执行的操作,它并不是真正地更改save方法,而是在保存节点时更改重定向。

在这种情况下,做一个像Drupal 7一样的工作,hook_form_alter以及一个自定义的提交处理程序(在表单或按钮上,取决于表单和要求)将是一个很好的解决方案。

您在问题中描述的内容也可以使用,但是除非我确实想更改类中的内容,否则我将避免覆盖基类。

无论如何,save方法仅用作提交处理程序,因此仅添加重定向就没有太大意义。


0

我认为更好的方法是仍然使用form_alter系列中的一个钩子,附加一个提交处理程序,并在其中设置重定向。

在我看来,扩展基类来做到这一点是毛茸茸的。特别是因为没有功能在更改,因此只需重定向即可。


0

您可以创建一个新的EventSubscriber来侦听KernelEvents :: REQUEST事件,然后在提交节点表单时做出反应,如下所示

无论如何,hook_form_alter方法可以正常工作。


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);

这是因为表单现在已完全构建,而不是表单alter hook本身的情况。

这个想法是:您可以添加一个验证处理程序作为最后一个处理程序,评估存在于提交中的其他处理程序,然后在此处进行更改。

如果您还想更改验证处理程序,请确保您的验证处理程序先运行,然后在验证处理程序中更改所需的内容。

我自己仍在寻找更好的方法,我只需要始终替换用户注册表单的验证/提交处理程序即可。但是可能存在其他破坏我的模块实现的模块。因此,我的模块将需要能够检查这些,并且这种方式是可行的。我确实想知道是否存在构建功能后的某种实体形式来实现这一目标。(在表单完成并即将交付时运行的内容)(对于这种简单情况,这并不复杂)

绕过save()方法的重定向是不可能的,但是通过这种方式取消save()的设置(+实现您自己的)。的确,一个类更好,并且可以更轻松地访问对象/等,但是重写核心类确实会在其他模块想要使用它们时引发问题。如果使用此代码,则不是这种情况。


0

检查完此问题后,我发现这应该适合您的情况:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.