web-dev-qa-db-ja.com

1つのエンティティフォームを別のエンティティフォームに埋め込み、両方を保存する

ユーザーエンティティに依存するカスタムエンティティがあります。実際、エンティティフォームをユーザープロファイルフォーム内に表示するのが理にかなっていると感じたのは、非常に重要です。

enter image description here

私が今抱えている問題は次のとおりです。 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で使用されていました)をシャッフルすることを望んでいましたが、その配列は巨大で、送信ボタンとハンドラーを見つけることができませんでした必要だった。

だから問題は、これを行うことができるのですか?そして、それを行うための推奨される方法は何でしょうか?

9
Neograph734

自分でやろうとするのではなく、 インラインエンティティフォーム モジュールを試してみてください。このモジュールは、この特定のケース(エンティティフォーム内のエンティティの作成/編集)のために作成されています。

Drupal Commerceのワークフローを改善するためにこれに多くの作業が行われていることを知っています。つまり、これはうまく機能しているはずです。私自身はテストしていませんが、Drupal CommerceはDrupal 8にも依存しているため、すでに非常に安定しています。

このモジュールは、フォームを作成するエンティティ参照フィールドにウィジェットを追加することで機能するため、ほとんどプラグアンドプレイである必要があります。唯一の要件は、ユーザーがカスタムエンティティへの参照を持っていることです。

10
googletorp

これは可能だと思います。残念ながら、今日はコードを書く時間はありませんが、次の点に注意してください。

  • サブフォームを追加するときは、送信されたフォームを認識するためにDrupalで使用される_form_id_や_form_build_id_などの特別なアイテムを必ず削除してください。
  • 2番目のフォームのフォームボタンが不要な場合は、サブフォームをメインフォームに追加する前に、unset($sub_form['actions'])などのフォームアイテムを削除する必要があります。
  • POST変数の別のポケットでサブフォームの値をキャッチできるように、フォームで_#tree_を有効にしてください。例:_$form['#tree'] = TRUE; $form['sub-form'] = $sub_form;_これにより、 _$form_state['values']['sub-form']_。で使用できるサブフォーム値
    • ユーザーがサブフォームを個別に送信できるようにする場合は、サブフォームのアクションの名前を変更して、どのボタンがクリックされたかを後で認識できるようにする必要があります。ユーザーが1つだけの保存ボタンを使用して両方のものを保存するようにしたい場合は、問題が少ないので、このサブポイントは無視してください。
  • これでフォームがUIに表示されたので、次のステップは送信を処理することです。これを行うには、メインフォームに フォーム送信コールバック を追加します。また、サブフォームの検証コールバックをメインフォームに追加することもできます。カスタムコールバックでは、サブフォームの送信コールバックをトリガーする必要があります。 Drupal 7以前使用していた drupal_form_submit で、Drupal 8に相当するものはまだありません。代わりに、サブをトリガーすることもできます。 -formの送信コールバックは、最悪のシナリオでは手動でコールバックしますが、_sub-form_の_$form_state['values']_値のみを渡すようにしてください(私が何を意味するのか理解してください)。
  • サブフォームのコールバックがエラーなしで機能すると、両方のフォームが正常に送信されて処理されたと想定できます。

それが役に立てば幸い!実験の地獄のように聞こえます!幸運を。

7
Jigarius

理論的な答え(うまくいかないものですが、これは私が得た最も近いものです)。参考のためにここに投稿し、他の人のための出発点。

ユーザーフォームを変更します。

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.
}
1
Neograph734