web-dev-qa-db-fra.com

Incorporez un formulaire d'entité dans un autre et enregistrez les deux

J'ai une entité personnalisée, qui dépend de l'entité utilisateur. En fait, c'est tout de même selon que je sentais qu'il était logique d'afficher mon formulaire d'entité dans le formulaire de profil utilisateur:

enter image description here

Le problème que j'ai maintenant est le suivant; il y a 2 boutons de sauvegarde. Et s'il n'est pas assez mauvais, le bouton d'enregistrement pour l'utilisateur (celui du bas) ne fonctionne même plus et le bouton d'enregistrement d'étiquette blanche enregistre uniquement l'entité d'étiquette blanche.

Le formulaire est modifié dans le formulaire utilisateur comme ceci:

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

J'espérais mélanger certains paramètres dans le $whitelabel_form array (qui fonctionnait dans Drupal 7), mais ce tableau est énorme et je n'ai pas pu trouver les boutons de soumission et le gestionnaire dont j'avais besoin.

La question est donc de savoir si cela peut être fait? Et quelle serait la manière recommandée de le faire?

9
Neograph734

Au lieu d'essayer de faire votre propre truc, vous devriez essayer le module Inline Entity Form . Ce module est conçu pour ce cas spécifique (création/modification d'entités dans des formulaires d'entité).

Je sais que beaucoup de travail a été fait pour améliorer le flux de travail dans Drupal Commerce, ce qui signifie que cela devrait bien fonctionner. Je ne l'ai pas testé moi-même, mais depuis Drupal Commerce en dépend dans Drupal 8 également, il devrait déjà être assez stable).

Le module fonctionne en ajoutant un widget au champ de référence d'entité qui crée le formulaire, il devrait donc être à peu près plug and play. La seule exigence est que l'utilisateur ait une référence à votre entité personnalisée.

10
googletorp

Je pense que cela devrait être possible. Malheureusement, je n'ai pas le temps d'écrire du code aujourd'hui, cependant, je pense que vous devez garder les choses suivantes à l'esprit:

  • Lors de l'ajout du sous-formulaire, assurez-vous de supprimer les éléments spéciaux tels que form_id Et form_build_id Utilisés par Drupal pour reconnaître le formulaire qui a été soumis.
  • Si vous ne souhaitez pas les boutons de formulaire dans le deuxième formulaire, vous devez supprimer cet élément de formulaire comme unset($sub_form['actions']) avant d'ajouter le sous-formulaire au formulaire principal.
  • Assurez-vous que vous activez #tree Pour le formulaire afin que vous puissiez intercepter les valeurs de sous-formulaire dans une poche séparée dans la variable POST. Exemple, $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; This rendra vos valeurs de sous-formulaire disponibles dans $form_state['values']['sub-form'].
    • Si vous souhaitez que les utilisateurs puissent soumettre le sous-formulaire indépendamment, vous devrez renommer les actions pour le sous-formulaire afin de pouvoir ultérieurement reconnaître le bouton sur lequel vous avez cliqué. Si vous souhaitez que l'utilisateur n'utilise qu'un seul bouton d'enregistrement pour enregistrer les deux choses, il y aura moins de problèmes, alors ignorez ce sous-point.
  • Maintenant que le formulaire est visible dans l'interface utilisateur, l'étape suivante consiste à gérer la soumission. Pour ce faire, ajoutez un rappel de soumission de formulaire à votre formulaire principal. Vous pouvez également ajouter les rappels de validation du sous-formulaire au formulaire principal. Dans le rappel personnalisé, vous devrez déclencher le rappel de soumission pour le sous-formulaire. Dans Drupal 7 que nous avions l'habitude de faire drupal_form_submit - je ne sais pas l'équivalent pour Drupal 8 pour le moment. Alternativement, vous pouvez déclencher le sous -form de rappel de soumission manuellement dans le pire des cas, mais assurez-vous de ne transmettre que les valeurs sub-form dans $form_state['values'] (j'espère que vous comprenez ce que je veux dire).
  • Une fois que le rappel de sous-formulaire fonctionne sans erreur, vous pouvez supposer que les deux formulaires ont été soumis et traités avec succès!

J'espère que cela aide! Cela ressemble à un enfer d'une expérience! Bonne chance.

7
Jigarius

La réponse théorique (celle qui ne fonctionne pas, mais c'est la plus proche que j'ai obtenue). Poster ici pour référence et un point de départ pour les autres.

Modifiez le formulaire utilisateur.

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

Soumettre le gestionnaire:

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