将一个实体表单嵌入到另一个实体表单中,然后保存两者


9

我有一个自定义实体,这取决于用户实体。实际上,即使如此,我仍然认为有必要在用户个人资料表单中显示我的实体表单:

在此处输入图片说明

我现在遇到的问题如下:有2个保存按钮。并且,如果还不够好,则用户(下一个)的保存按钮甚至不再起作用,并且白色标签保存按钮仅保存白色标签实体。

将该表单更改为用户表单,如下所示:

function whitelabel_form_user_form_alter(&$form, FormStateInterface $form_state) {

  $whitelabel = WhiteLabel::load(1);

  $whitelabel_form = \Drupal::service('entity.manager')
    ->getFormObject('whitelabel', 'default')
    ->setEntity($whitelabel);

  $form['whitelabel'] = array(
    '#type' => 'details',
    '#title' => t('White label settings'),
    '#open' => TRUE,
    'form' => \Drupal::formBuilder()->getForm($whitelabel_form),
  );
}

我希望改组$whitelabel_form数组中的某些参数(以前在Drupal 7中使用过),但是该数组很大,无法找到所需的提交按钮和处理程序。

所以问题是,可以做到吗?推荐的方法是什么?



谢谢,我实际上早些时候读过这个问题,但是无论我尝试了什么,我都找不到。我来看一下
Neograph734 '17

@Eyal,您还知道不需要我覆盖表格的方法吗?我希望保留用户表格原样。
Neograph734

我编写了一个自定义模块Entity_reference_form,但维护不够。如果要避免自定义代码,则可能应该使用inline_entity_form。
Eyal

@Eyal,我不害怕自定义代码(我正在编写模块:p)。但是在您的示例中,您将创建一个不再是用户表单的多表单。这意味着,每当有人尝试在另一个模块中执行相同的操作时,您总是只会看到3种(或更多种)可用形式中的2种。这就是我的自负。但是,感谢您抽出宝贵时间与我联系。我将在2天后再看一下内联实体表单,但是我愿意接受以某种方式更改它的替代方法。
Neograph734

Answers:


10

而不是尝试做自己的事情,您应该尝试内联实体表单模块。此模块是针对特定情况(在实体表单中创建/编辑实体)而制作的。

我知道,为了改善Drupal Commerce中的工作流程,已经进行了很多工作,这意味着它应该能很好地工作。我还没有亲自测试过它,但是由于Drupal Commerce在Drupal 8中也依赖它,因此它应该已经很稳定了。

该模块通过将小部件添加到创建表单的实体引用字段中来工作,因此应该即插即用。唯一的要求是用户必须引用您的自定义实体。


我确实调查了一下,但未显示引用的实体形式。不过,那对我来说可能是个错误……
Neograph734 '17

内联实体表单并不支持所有实体,如果这是一个自定义实体,那么您将需要为自定义类型的实体编写插件。默认情况下不支持文件实体,并且需要此功能。
Frank Robert Anderson

7

我相信这应该是可能的。不幸的是,我今天没有时间编写代码,但是,我认为您应该牢记以下几点:

  • 虽然附加子窗体,请确保您删除特殊项目,如form_idform_build_id使用Drupal的识别哪些形式提交。
  • 如果您不希望第二个表单中的表单按钮,则需要删除该表单项,就像unset($sub_form['actions'])在将子表单追加到主表单之前一样。
  • 确保启用#tree该表单,以便可以在POST变量的单独口袋中捕获子表单的值。例如,$form['#tree'] = TRUE; $form['sub-form'] = $sub_form; 这将使您的子表单值可在中使用$form_state['values']['sub-form']
    • 如果希望用户能够独立提交子表单,则必须重命名子表单的操作,以便以后可以识别单击了哪个按钮。如果希望用户仅使用一个保存按钮来保存所有内容,那么麻烦就少了,因此可以忽略此子点。
  • 现在,该窗体在UI中可见,下一步将是处理提交。为此,向您的主表单添加一个表单提交回调。您可能还希望将子表单的验证回调也添加到主表单中。在自定义回调中,您将必须触发子表单的提交回调。在Drupal 7中,我们曾经做过drupal_form_submit-我不知道Drupal 8的等效功能。另外,在最坏的情况下,您可以手动触发子表单的提交回调,但是请确保仅传递sub-form$form_state['values'](希望您理解我的意思)。
  • 子表单回调正常运行后,您可以假定两个表单都已成功提交和处理!

希望能帮助到你!听起来像是一个实验的地狱!祝好运。


1
谢谢,我已经在论坛中显示了我的初始代码。除去form_build_idform_tokenform_idactions取得了按钮消失,再次提出了“外在形式”的工作。我将对此进行更多介绍,并告诉您它是如何工作的。
Neograph734 '17

我授予您赏金,因为这是回答问题的最佳尝试。我仍在为此苦苦挣扎,因为表格拒绝进入“树状模式”。无论我尝试什么,所有值都始终存储在顶层。而且似乎提交的值也不在$form_state ['values'](表单元素键为空)。可能还没有,但是我希望有一天能解决。
Neograph734

1

理论上的答案(不起作用,但这是我得到的最接近的答案)。在此处发布以供参考和其他参考。

更改用户表单。

function whitelabel_form_user_form_alter(&$form, FormStateInterface $form_state) {
  $whitelabel = WhiteLabel::load(1);

  $whitelabel_form = \Drupal::entityTypeManager()
    ->getFormObject('whitelabel', 'default')
    ->setEntity($whitelabel);
  $renderable_form = \Drupal::formBuilder()->getForm($whitelabel_form);

  // Remove embedded form specific data.
  unset($renderable_form['actions']);
  unset($renderable_form['form_build_id']);
  unset($renderable_form['form_token']);
  unset($renderable_form['form_id']);

  // Also remove all other properties that start with a '#'.
  foreach ($renderable_form as $key => $value) {
    if (strpos($key, '#') === 0) {
      unset ($renderable_form[$key]);
    }
  }

  // Create a container for the entity's fields.
  $form['whitelabel'] = array(
    '#type' => 'details',
    '#title' => t('White label settings'),
    '#open' => TRUE,
    '#tree' => TRUE,
  );
  $form['whitelabel'] += $renderable_form;

  $form['actions']['submit']['#submit'][] = 'whitelabel_form_user_form_submit';
}

提交处理程序:

function whitelabel_form_user_form_submit(&$form, FormStateInterface $form_state) {
  $values = $form_state->getValues(); 

  $form_state = new FormState();
  $form_state->setValues($values);
  // Theoretically you'd want to use $values['entity_container']
  // for the dedicated entity values.

  // Obtain or create an entity. (You want to get this from the form.)
  if (!$whitelabel = WhiteLabel::load(1)) {
    $whitelabel = WhiteLabel::create();
  }

\Drupal::entityTypeManager()
  ->getFormObject('whitelabel', 'default')
  ->setEntity($whitelabel) // Current entity.
  ->buildEntity($form, $form_state) // Update with form values.
  ->save(); // Save updated entity.
}
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.