Bir varlık formunu diğerine gömün ve her ikisini de kaydedin


9

Kullanıcı varlığına bağlı özel bir varlık var. Aslında, öyle bile bağlı olarak ben varlığım formu kullanıcı profili formu içinde görüntülemek mantıklı hissettim:

resim açıklamasını buraya girin

Şu an yaşadığım sorun şudur; 2 kaydetme düğmesi vardır. Ve yeterince kötü değilse, kullanıcı için (altta bulunan) kaydet düğmesi artık çalışmaz ve beyaz etiket kaydetme düğmesi yalnızca beyaz etiketli varlığı kaydeder.

Form, kullanıcı formuna şu şekilde değiştirilir:

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'de kullanılan) dizideki bazı parametreleri karıştırmayı umuyordum , ama bu dizi muazzam ve gönderme düğmeleri ve gerekli olan işleyiciyi bulamadım.

Yani soru şu, bu yapılabilir mi? Ve bunu yapmanın önerilen yolu ne olabilir?



Teşekkürler, aslında bu soruyu daha önce okudum ama ne denediğim önemli değil, onu bulamadım. Bir göz
atacağım

@Eyal, formu geçersiz kılmamı gerektirmeyen bir yöntem de biliyor musunuz? Kullanıcı formunu olduğu gibi tutmayı tercih ederim.
Neograph734

Bir özel modül entity_reference_form yazdım ama yeterince korunmuyor. Özel koddan kaçınmak istiyorsanız, muhtemelen inline_entity_form kullanmalısınız.
Eyal

@Eyal, özel koddan korkmuyorum (bir modül yazıyorum: p). Ancak örneğinizde, artık kullanıcı formu olmayan bir çok biçim oluşturursunuz. Bu, başka biri başka bir modülde aynı numarayı yapmaya çalıştığında, her zaman mevcut 3 (veya daha fazla) formdan yalnızca 2 tanesini göreceğiniz anlamına gelir. Beni böyle düşünüyor. Ama bana geri dönmeye zaman ayırdığın için teşekkürler. Satır içi varlık formuna 2 gün içinde bir kez daha bakacağım, ancak bir şekilde değiştirmek için alternatiflere açık olacağım.
Neograph734

Yanıtlar:


10

Kendi işinizi yapmaya çalışmak yerine Inline Entity Form modülünü denemelisiniz . Bu modül bu özel durum için yapılır (varlık formlarında varlık oluşturma / düzenleme).

Drupal Commerce'deki iş akışını iyileştirmek için bunun üzerine çok çalışma yapıldığını biliyorum, bu da bunun iyi çalışması gerektiği anlamına geliyor. Kendimi test etmedim, ancak Drupal Ticaret Drupal 8'de de ona bağlı olduğundan, zaten oldukça kararlı olmalı.

Modül, formu oluşturan varlık referans alanına bir widget ekleyerek çalışır, bu yüzden hemen hemen tak ve çalıştır olmalıdır. Tek gereksinim, kullanıcının özel varlığınıza referans olmasıdır.


Buna baktım, ancak başvurulan varlık formu görünmedi. Bu benim açımdan bir hata olabilirdi ...
Neograph734

Tüm varlıklar Inline Entity Form tarafından desteklenmez, bu özel bir varlıksa, özel türünüzdeki varlıklar için bir eklenti yazmanız gerekir. Dosya varlıkları varsayılan olarak desteklenmez ve bunu gerektirir.
Frank Robert Anderson

7

Bunun mümkün olması gerektiğine inanıyorum. Ne yazık ki, bugün kod yazmak için zamanım yok, ancak, aşağıdaki şeyleri aklınızda tutmanız gerektiğini düşünüyorum:

  • Alt formu ekleme ederken, emin gibi özel öğeleri kaldırmak yapmak form_idve form_build_idsunuldu hangi form tanımak için Drupal tarafından kullanılan.
  • İkinci formdaki form düğmelerini istemiyorsanız unset($sub_form['actions']), alt formu ana forma eklemeden önce bu form öğesini kaldırmanız gerekir .
  • #treePOST değişkeninde alt form değerlerini ayrı bir cepte yakalayabilmeniz için formu etkinleştirdiğinizden emin olun . Örnek, $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; Bu, alt form değerlerinizi içinde kullanılabilir hale getirecektir $form_state['values']['sub-form'].
    • Kullanıcıların alt formu bağımsız olarak gönderebilmesini istiyorsanız, daha sonra hangi düğmenin tıklandığını algılayabilmeniz için alt formun eylemlerini yeniden adlandırmanız gerekir. Kullanıcının her iki şeyi de kaydetmek için yalnızca bir kaydet düğmesi kullanmasını istiyorsanız, daha az sorun olur, bu nedenle bu alt noktayı göz ardı edin.
  • Şimdi, form kullanıcı arayüzünde görülebildiğinden, bir sonraki adım gönderimi işlemek olacaktır. Bunu yapmak için, ana formunuza bir form gönderme geri araması ekleyin . Ayrıca alt formun doğrulama geri çağrılarını ana forma da eklemek isteyebilirsiniz. Özel geri aramada, alt form için gönderme geri aramasını tetiklemeniz gerekir. Drupal 7'de drupal_form_submit yapıyorduk - Drupal 8'in eşdeğerini henüz bilmiyorum. Alternatif olarak, en kötü senaryoda alt formun geri gönderme çağrılarını manuel olarak tetikleyebilirsiniz, ancak yalnızca sub-formdeğerleri ilettiğinizden emin olun $form_state['values'](umarım ne demek istediğimi anlarsınız).
  • Alt form geri araması hatasız çalıştığında, her iki formun da başarıyla gönderildiğini ve işlendiğini varsayabilirsiniz!

Umarım yardımcı olur! Bir denemenin cehennemi gibi geliyor! İyi şanslar.


1
Teşekkürler, zaten ilk kodumla gösterilecek forumu aldım. Çıkarma form_build_id, form_token, form_idve actionsdüğme yapılan kaybolur ve tekrar 'dış formu çalışmalarını yaptı. Bununla biraz daha oynayacağım ve nasıl çalıştığını size bildireceğim.
Neograph734

Size ödül veriyorum çünkü soruyu cevaplamak için en iyi girişim bu. Bununla hala mücadele ediyorum çünkü form 'ağaç moduna' girmeyi reddediyor. Ne denediğim önemli değil, tüm değerler her zaman en üst düzeyde saklanır. Ve gönderilen değerler de içinde değil gibi görünüyor $form_state ['values'](form öğesi anahtarları boş). Muhtemelen mümkün değil (henüz), ama umarım bunu bir gün çözebilirim.
Neograph734

1

Teorik cevap (işe yaramayan, ama bu en yakın olanı). Burada referans için gönderme ve diğerleri için bir başlangıç ​​noktası.

Kullanıcı formunu değiştirin.

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

İşleyiciyi gönder:

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.
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.