it-swarm.com.de

Betten Sie ein Entitätsformular in ein anderes ein und speichern Sie beide

Ich habe eine benutzerdefinierte Entität, die von der Benutzerentität abhängt. Tatsächlich hängt es jedoch davon ab, dass ich es für sinnvoll hielt, mein Entitätsformular im Benutzerprofilformular anzuzeigen:

(enter image description here

Das Problem, das ich jetzt habe, ist das folgende; Es gibt 2 Speichern-Schaltflächen. Und wenn es nicht schlimm genug ist, funktioniert die Schaltfläche zum Speichern für den Benutzer (die untere) nicht mehr und die Schaltfläche zum Speichern von weißen Etiketten speichert nur die Entität für weiße Etiketten.

Das Formular wird wie folgt in das Benutzerformular geändert:

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

Ich hatte gehofft, einige Parameter in der $whitelabel_form Array (das früher in Drupal 7) funktioniert hat, aber dieses Array ist riesig und ich konnte die Submit-Buttons und den Handler nicht finden, die ich brauchte.

Die Frage ist also, kann dies getan werden? Und was wäre die empfohlene Vorgehensweise?

9
Neograph734

Anstatt zu versuchen, Ihr eigenes Ding zu machen, sollten Sie das Modul Inline Entity Form ausprobieren. Dieses Modul wurde für diesen speziellen Fall erstellt (Erstellen/Bearbeiten von Entitäten in Entitätsformularen).

Ich weiß, dass viel Arbeit investiert wurde, um den Workflow in Drupal Commerce) zu verbessern, was bedeutet, dass dies gut funktionieren sollte. Ich habe es nicht selbst getestet, aber seitdem Drupal Commerce hängt davon ab in Drupal 8 auch, es sollte schon ziemlich stabil sein.

Das Modul fügt dem Entitätsreferenzfeld, mit dem das Formular erstellt wird, ein Widget hinzu, sodass es praktisch Plug-and-Play-fähig sein sollte. Die einzige Voraussetzung ist, dass der Benutzer einen Verweis auf Ihre benutzerdefinierte Entität hat.

10
googletorp

Ich glaube, das sollte möglich sein. Leider habe ich heute keine Zeit, Code zu schreiben. Ich denke jedoch, dass Sie Folgendes beachten sollten:

  • Stellen Sie beim Anhängen des Unterformulars sicher, dass Sie spezielle Elemente wie form_id Und form_build_id Entfernen, die von Drupal verwendet werden, um zu erkennen, welches Formular gesendet wurde).
  • Wenn Sie die Formularschaltflächen im zweiten Formular nicht möchten, müssen Sie dieses Formularelement wie unset($sub_form['actions']) entfernen, bevor Sie das Unterformular an das Hauptformular anhängen.
  • Stellen Sie sicher, dass Sie #tree Für das Formular aktivieren, damit Sie die Unterformularwerte in einer separaten Tasche in der Variablen POST.) Abfangen können. Beispiel: $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; Dies stellt Ihre Unterformularwerte in $form_state['values']['sub-form'] zur Verfügung.
    • Wenn Sie möchten, dass Benutzer das Unterformular unabhängig senden können, müssen Sie die Aktionen für das Unterformular umbenennen, damit Sie später erkennen können, auf welche Schaltfläche geklickt wurde. Wenn Sie möchten, dass der Benutzer nur eine Schaltfläche zum Speichern verwendet, um beide Dinge zu speichern, gibt es weniger Probleme. Ignorieren Sie diesen Unterpunkt.
  • Nachdem das Formular in der Benutzeroberfläche angezeigt wird, besteht der nächste Schritt darin, die Übermittlung zu behandeln. Fügen Sie dazu Ihrem Hauptformular ein Rückruf zur Formularübermittlung hinzu. Möglicherweise möchten Sie auch die Validierungsrückrufe des Unterformulars zum Hauptformular hinzufügen. Im benutzerdefinierten Rückruf müssen Sie den Übermittlungsrückruf für das Unterformular auslösen. In Drupal 7 haben wir früher drupal_form_submit - Ich weiß nicht, was Drupal 8 noch entspricht. Alternativ können Sie das Sub auslösen -forms Übermittlungsrückrufe manuell im schlimmsten Fall, aber stellen Sie sicher, dass Sie nur die sub-form - Werte in $form_state['values'] übergeben (ich hoffe, Sie verstehen, was ich meine).
  • Sobald der Rückruf des Unterformulars fehlerfrei funktioniert, können Sie davon ausgehen, dass beide Formulare erfolgreich gesendet und verarbeitet wurden!

Ich hoffe es hilft! Klingt nach einem verdammt guten Experiment! Viel Glück.

7
Jigarius

Die theoretische Antwort (eine, die nicht funktioniert, aber die nächste, die ich bekommen habe). Hier als Referenz und Ausgangspunkt für andere posten.

Ändern Sie das Benutzerformular.

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';
}

Handler senden:

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