एक इकाई फ़ॉर्म को दूसरे में एम्बेड करें और दोनों को सहेजें


9

मेरे पास एक कस्टम इकाई है, जो उपयोगकर्ता इकाई पर निर्भर है। वास्तव में, यह इसलिए भी निर्भर करता है कि मुझे लगा कि यूजर प्रोफाइल फॉर्म में अपनी इकाई के रूप को प्रदर्शित करने के लिए यह समझ में आया:

यहाँ छवि विवरण दर्ज करें

अब मुझे जो समस्या हो रही है, वह निम्नलिखित है; 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सरणी में कुछ मापदंडों को फेरबदल करने की उम्मीद कर रहा था (जो कि ड्रुपल 7 में काम करता था), लेकिन वह सरणी बहुत बड़ी है और मुझे सबमिट बटन और हैंडलर नहीं मिल पाए जिनकी मुझे जरूरत थी।

तो सवाल यह है कि क्या ऐसा किया जा सकता है? और इसे करने का अनुशंसित तरीका क्या होगा?


इस उत्तर को देखें: drupal.stackexchange.com/questions/203405/…
Eyal

धन्यवाद, मैंने वास्तव में उस प्रश्न को पहले पढ़ा था, लेकिन कोई फर्क नहीं पड़ता कि मैंने क्या कोशिश की, मैं इसे नहीं पा सका। मैं एक नज़र हूँ
Neograph734

@ फिर, क्या आप एक ऐसी विधि भी जानते हैं जिससे मुझे फॉर्म को ओवरराइड करने की आवश्यकता नहीं है? मैं उपयोगकर्ता रूप रखना पसंद करूंगा।
Neograph734

मैंने एक कस्टम मॉड्यूल Unit_reference_form लिखा है लेकिन यह पर्याप्त रूप से अनुरक्षित नहीं है। यदि आप कस्टम कोड से बचना चाहते हैं, तो आपको शायद inline_entity_form का उपयोग करना चाहिए।
ईयल

@ ईयाल, मैं कस्टम कोड से डरता नहीं हूं (मैं एक मॉड्यूल लिख रहा हूं: पी)। लेकिन आपके उदाहरण में आप एक मल्टीफॉर्म बनाते हैं जो अब उपयोगकर्ता रूप नहीं है। इसका मतलब यह है कि जब भी कोई अन्य मॉड्यूल में उसी चाल को करने का प्रयास करता है, तो आप हमेशा केवल 3 में से 2 (या अधिक) उपलब्ध प्रपत्र देखेंगे। यही मेरी कल्पना करता है। लेकिन मुझे वापस पाने के लिए समय निकालने के लिए धन्यवाद। मेरे पास 2 दिनों में इनलाइन एंटिटी फॉर्म पर एक और नज़र होगी, लेकिन मैं इसे किसी भी तरह से बदलने पर विकल्प के लिए खुला रहूंगा।
नेओगोर 734

जवाबों:


10

अपनी खुद की कोशिश करने के बजाय, आपको इनलाइन एंटिटी फॉर्म मॉड्यूल की कोशिश करनी चाहिए । यह मॉड्यूल इस विशिष्ट मामले के लिए बनाया गया है (इकाई रूपों के भीतर संस्थाओं को बनाना / संपादित करना)।

मुझे पता है कि ड्रुपल कॉमर्स में वर्कफ़्लो को बेहतर बनाने के लिए इसमें बहुत सारे काम किए गए हैं, जिसका मतलब है कि यह अच्छी तरह से काम करना चाहिए। मैंने स्वयं इसका परीक्षण नहीं किया है, लेकिन चूंकि Drupal Commerce Drupal 8 में भी इस पर निर्भर है, इसलिए यह पहले से ही काफी स्थिर होना चाहिए।

मॉड्यूल इकाई के संदर्भ क्षेत्र में एक विजेट जोड़कर काम करता है जो फॉर्म बनाता है, इसलिए इसे बहुत अधिक प्लग और खेलना चाहिए। केवल आवश्यकता यह है कि उपयोगकर्ता के पास आपकी कस्टम इकाई का संदर्भ हो।


मैंने उस पर गौर किया, लेकिन संदर्भित इकाई फॉर्म नहीं दिखा। हालाँकि, मेरी ओर से यह एक त्रुटि हो सकती है ...
Neograph734

इनलाइन एंटिटी फॉर्म द्वारा सभी संस्थाओं का समर्थन नहीं किया जाता है, यदि यह एक कस्टम इकाई है तो आपको अपने कस्टम प्रकार की संस्थाओं के लिए एक प्लगइन लिखना होगा। फ़ाइल संस्थाएँ डिफ़ॉल्ट रूप से समर्थित नहीं हैं और इसके लिए आवश्यकता होती है।
फ्रैंक रॉबर्ट एंडरसन

7

मेरा मानना ​​है कि यह संभव होना चाहिए। दुर्भाग्य से, मेरे पास आज कोड लिखने का समय नहीं है, हालांकि, मुझे लगता है कि आपको निम्नलिखित बातों को ध्यान में रखना चाहिए:

  • उप-प्रपत्र को संलग्न करते समय, सुनिश्चित करें कि आप विशेष आइटम जैसे ड्रुपल को निकालते हैं form_idऔर form_build_idयह पहचानते हैं कि कौन सा फ़ॉर्म सबमिट किया गया था।
  • यदि आप दूसरे फ़ॉर्म में फ़ॉर्म बटन नहीं चाहते हैं, तो unset($sub_form['actions'])आपको उप-फ़ॉर्म को मुख्य फ़ॉर्म में जोड़ने से पहले उस प्रपत्र आइटम को निकालने की आवश्यकता होगी ।
  • सुनिश्चित करें कि आप #treeफॉर्म के लिए सक्षम हैं ताकि आप पोस्ट-वैरिएबल में एक अलग पॉकेट में उप-फॉर्म वैल्यू को पकड़ सकें। उदाहरण, $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; यह आपके उप-प्रपत्र मान को उपलब्ध कराएगा $form_state['values']['sub-form']
    • यदि आप चाहते हैं कि उपयोगकर्ता उप-फ़ॉर्म को स्वतंत्र रूप से सबमिट करने में सक्षम हों, तो आपको उप-प्रपत्र के लिए कार्यों का नाम बदलना होगा ताकि आप बाद में पहचान सकें कि किस बटन पर क्लिक किया गया था। यदि आप चाहते हैं कि उपयोगकर्ता दोनों चीजों को बचाने के लिए केवल एक ही सेव बटन का उपयोग करे, तो इस उप-बिंदु को अनदेखा करने से कम परेशानी होगी।
  • अब, यह फ़ॉर्म UI में दिखाई दे रहा है, अगला चरण सबमिशन को संभालने के लिए होगा। ऐसा करने के लिए, अपने मुख्य फ़ॉर्म में फ़ॉर्म सबमिशन कॉलबैक जोड़ें । आप उप-प्रपत्र के सत्यापन कॉलबैक को मुख्य रूप में भी जोड़ना चाह सकते हैं। कस्टम कॉलबैक में, आपको सब-फॉर्म के लिए सबमिशन कॉलबैक को ट्रिगर करना होगा। Drupal 7 में हम drupal_form_submit करते थे - मैं Drupal 8 के लिए अभी तक समान नहीं हूं। वैकल्पिक रूप से, आप सब-फ़ॉर्म की सबमिशन कॉलबैक को सबसे खराब स्थिति में मैन्युअल रूप से ट्रिगर कर सकते हैं, लेकिन सुनिश्चित करें कि आप केवल sub-formमानों को पास करते हैं $form_state['values'](आशा है कि आप समझते हैं कि मेरा क्या मतलब है)।
  • एक बार उप-प्रपत्र कॉलबैक त्रुटियों के बिना काम करता है, तो आप मान सकते हैं कि दोनों रूपों को सबमिट किया गया था और सफलतापूर्वक संसाधित किया गया था!

आशा है ये मदद करेगा! एक प्रयोग के एक नरक की तरह लगता है! सौभाग्य।


1
धन्यवाद, मुझे अपने शुरुआती कोड के साथ पहले ही दिखाने के लिए मंच मिल गया। को हटाने form_build_id, form_token, form_idऔर actionsबटन बनाया गायब हो जाते हैं और 'बाहरी रूप के काम फिर से बनाया है। मैं इसके साथ कुछ और खेलूंगा और आपको बताऊंगा कि यह कैसे काम करता है।
नियोग .३४

मैं आपको इनाम देने का सम्मान कर रहा हूं क्योंकि यह सवाल का जवाब देने का सबसे अच्छा प्रयास है। मैं अभी भी इससे जूझ रहा हूं क्योंकि फॉर्म 'ट्री मोड' में जाने से इनकार करता है। सभी मान हमेशा शीर्ष स्तर पर संग्रहीत किए जाते हैं, चाहे मैं कोई भी प्रयास करूं। और ऐसा लगता है कि सबमिट किए गए मान भी नहीं हैं $form_state ['values'](फॉर्म एलिमेंट कीज़ खाली हैं)। यह शायद (अभी तक) संभव नहीं है, लेकिन मुझे किसी दिन यह पता लगाने की उम्मीद है।
Neograph734

1

सैद्धांतिक उत्तर (एक जो काम नहीं करता है, लेकिन यह मेरे निकटतम है)। संदर्भ के लिए यहां पोस्टिंग और दूसरों के लिए एक प्रारंभिक बिंदु।

उपयोगकर्ता प्रपत्र को बदल दें।

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.
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.