Incorporare un modulo entità in un altro e salvare entrambi


9

Ho un'entità personalizzata, che dipende dall'entità utente. In effetti, è anche così dipendente che ho ritenuto sensato visualizzare il mio modulo entità nel modulo del profilo utente:

inserisci qui la descrizione dell'immagine

Il problema che sto avendo ora è il seguente; ci sono 2 pulsanti di salvataggio. E se non è abbastanza male, il pulsante di salvataggio per l'utente (quello inferiore) non funziona nemmeno più e il pulsante di salvataggio dell'etichetta bianca salva solo l'entità dell'etichetta bianca.

Il modulo viene modificato nel modulo utente in questo modo:

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

Speravo di mescolare alcuni parametri $whitelabel_formnell'array (che un tempo funzionava in Drupal 7), ma quell'array è enorme e non sono riuscito a trovare i pulsanti di invio e il gestore di cui avevo bisogno.

Quindi la domanda è: è possibile farlo? E quale sarebbe il modo raccomandato di farlo?



Grazie, in realtà ho letto quella domanda prima, ma non importa cosa ho provato, non sono riuscito a trovarla. Darò un'occhiata
Neograph734,

@Eyal, conosci anche un metodo che non mi richiede di sostituire il modulo? Preferirei mantenere il modulo utente così com'è.
Neograph734,

Ho scritto un modulo personalizzato entity_reference_form ma non è abbastanza mantenuto. Probabilmente dovresti usare inline_entity_form se vuoi evitare il codice personalizzato.
Eyal,

@Eyal, non ho paura del codice personalizzato (sto scrivendo un modulo: p). Ma nel tuo esempio crei un multiform che non è più il modulo utente. Ciò significa che ogni volta che qualcun altro tenta di fare lo stesso trucco in un altro modulo, vedrai sempre solo solo 2 dei 3 (o più) moduli disponibili. Questo è ciò che mi concepisce. Ma grazie per aver dedicato del tempo a tornare da me. Daremo un'altra occhiata al modulo entità inline tra 2 giorni, ma sarei aperto a alternative per alterarlo in qualche modo.
Neograph734,

Risposte:


10

Invece di provare a fare le tue cose, dovresti provare il modulo Inline Entity Form . Questo modulo è realizzato per questo caso specifico (creazione / modifica di entità all'interno di moduli entità).

So che è stato dedicato molto lavoro a questo per migliorare il flusso di lavoro nel Drupal Commerce, il che significa che dovrebbe funzionare bene. Non l'ho provato da solo, ma poiché Drupal Commerce dipende anche da Drupal 8, dovrebbe essere già abbastanza stabile.

Il modulo funziona aggiungendo un widget al campo di riferimento dell'entità che crea il modulo, quindi dovrebbe essere praticamente plug and play. L'unico requisito è che l'utente abbia un riferimento alla tua entità personalizzata.


L'ho esaminato, ma il modulo entità di riferimento non è stato visualizzato. Questo avrebbe potuto essere un errore da parte mia ...
Neograph734,

Non tutte le entità sono supportate dal Modulo entità in linea, se si tratta di un'entità personalizzata, sarà necessario scrivere un plug-in per entità del tipo personalizzato. Le entità file non sono supportate per impostazione predefinita e lo richiedono.
Frank Robert Anderson,

7

Credo che questo dovrebbe essere possibile. Sfortunatamente, non ho tempo di scrivere codice oggi, tuttavia, penso che dovresti tenere a mente le seguenti cose:

  • Durante l'aggiunta del modulo secondario, assicurati di rimuovere elementi speciali come form_ide form_build_idutilizzati da Drupal per riconoscere quale modulo è stato inviato.
  • Se non si desidera i pulsanti del modulo nel secondo modulo, è necessario rimuovere l'elemento del modulo come unset($sub_form['actions'])prima di aggiungere il modulo secondario al modulo principale.
  • Assicurati di abilitare #treeil modulo in modo da poter catturare i valori del modulo secondario in una tasca separata nella variabile POST. Esempio, $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; questo renderà disponibili i valori del tuo sottomodulo $form_state['values']['sub-form'].
    • Se desideri che gli utenti siano in grado di inviare il modulo secondario in modo indipendente, dovrai rinominare le azioni per il modulo secondario in modo da poter riconoscere in seguito quale pulsante è stato fatto clic. Se si desidera che l'utente utilizzi un solo pulsante di salvataggio per salvare entrambe le cose, ci sarebbero meno problemi, quindi ignorare questo punto secondario.
  • Ora che il modulo è visibile nell'interfaccia utente, il passaggio successivo sarebbe gestire l'invio. Per fare ciò, aggiungi un callback di invio modulo al modulo principale. È inoltre possibile aggiungere anche i callback di convalida del modulo secondario al modulo principale. Nel callback personalizzato, dovrai attivare il callback di invio per il modulo secondario. In Drupal 7 facevamo drupal_form_submit - Non so ancora l'equivalente di Drupal 8. In alternativa, puoi attivare manualmente i callback di invio del sottomodulo nello scenario peggiore, ma assicurati di passare solo i sub-formvalori $form_state['values'](spero che tu capisca cosa intendo).
  • Una volta che il callback del modulo secondario funziona senza errori, puoi presumere che entrambi i moduli siano stati inviati ed elaborati correttamente!

Spero che sia d'aiuto! Sembra un inferno di un esperimento! In bocca al lupo.


1
Grazie, ho già mostrato il forum con il mio codice iniziale. Rimozione form_build_id, form_token, form_ide actionsrealizzato il pulsante scompaiono e reso nuovamente il lavoro 'forma esterna'. Ci giocherò ancora un po 'e ti farò sapere come ha funzionato.
Neograph734,

Ti sto premiando perché è il miglior tentativo di rispondere alla domanda. Sto ancora lottando con questo perché il modulo rifiuta di passare alla "modalità albero". Tutti i valori sono sempre memorizzati al livello più alto, qualunque cosa io provi. E sembra che anche i valori inviati non siano presenti $form_state ['values'](le chiavi dell'elemento del modulo sono vuote). Probabilmente non è possibile (ancora), ma spero di capirlo un giorno.
Neograph734,

1

La risposta teorica (una che non funziona, ma questa è la più vicina che ho ottenuto). Pubblicare qui come riferimento e un punto di partenza per gli altri.

Modifica il modulo utente.

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

Invia gestore:

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.
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.