यह कोई रहस्य नहीं है कि अक्सर तत्वों के तत्वों या समूहों को प्रपत्र में जोड़ने की आवश्यकता होती है, जिनमें से संख्या अनिश्चित या बड़ी हो सकती है ताकि उन्हें प्रपत्र के कॉन्फ़िगरेशन में स्पष्ट रूप से इंगित किया जा सके।
इसके अलावा, यह कोई रहस्य नहीं है कि इस मुद्दे को हल करने के लिए एक सामान्य दृष्टिकोण है - उप-वर्गों के माध्यम से तत्वों के समूहों को जोड़ना। इस दृष्टिकोण का तर्क सरल है - टेम्प्लेट में, आवश्यक तत्व समूहों को जावास्क्रिप्ट का उपयोग करके फॉर्म में जोड़ा जाता है, आने वाले तत्व समूहों की संख्या को हैंडलर में गणना की जाती है और, उनकी संख्या के अनुसार, सबफॉर्म जोड़े जाते हैं, फिर सबफॉर्म के साथ पूरे फॉर्म को मान्य किया जाता है।
मेरे लिए, इस दृष्टिकोण का ऋण यह है कि फॉर्म कॉन्फ़िगरेशन को एक अलग जगह (एक अलग कॉन्फ़िगरेशन फ़ाइल में) से निकालना लगभग असंभव है और इसे फॉर्म हैंडलर में "पूर्व-कॉन्फ़िगर किया गया" होना है।
मैं इस कार्यक्षमता को लागू करने वाले एक अलग प्रपत्र तत्व बनाकर इस समस्या को हल करने का प्रस्ताव करता हूं।
आइए इस के व्यावहारिक कार्यान्वयन के लिए आगे बढ़ें।
एक नया ZF प्रोजेक्ट बनाएं
% zf create project www.multielement.lo
हम एप्लिकेशन.इन कॉन्फ़िगरेशन फ़ाइल में jQuery समर्थन के साथ व्यू ऑब्जेक्ट को इनिशियलाइज़ करते हैं, हमारे हेल्पर्स के लिए पथ सेट करते हैं, जावास्क्रिप्ट लाइब्रेरी में संस्करण और पथ सेट करते हैं
resources.view[] = ""
resources.view.helperPath.ZendX_JQuery_View_Helper = "ZendX/JQuery/View/Helper"
resources.view.helperPath.My_JQuery_View_Helper = "My/JQuery/View/Helper"
resources.jquery.version = "1.7"
/ एप्लिकेशन / कंट्रोलर / में एक फॉर्म-कंट्रोलर बनाएं
<?php class FormController extends Zend_Controller_Action { public function indexAction() { $opts = array( 'elements' => array( 'firstname' => array( 'type' => 'Text', 'options' => array( 'label' => '' ) ), 'lastname' => array( 'type' => 'Text', 'options' => array( 'label' => '' ) ), 'items' => array( 'type' => 'MultiElement', 'options' => array( 'label' => '', 'required' => true, 'elements' => array( 'name' => array( 'type' => 'Text', 'options' => array( 'label' => '', 'required' => true ) ), 'type' => array( 'type' => 'Select', 'options' => array( 'label' => '', 'required' => true, 'multioptions' => array( 'green' => '', 'red' => '', 'blue' => '', ) ) ), 'price' => array( 'type' => 'Text', 'options' => array( 'label' => ', .', 'required' => true ) ), ) ) ), 'logons' => array( 'type' => 'MultiElement', 'options' => array( 'label' => ' ', 'required' => true, 'elements' => array( 'login' => array( 'type' => 'Text', 'options' => array( 'label' => '', 'required' => true ) ), 'passw' => array( 'type' => 'Text', 'options' => array( 'label' => '', 'required' => true ) ), 'type' => array( 'type' => 'Select', 'options' => array( 'label' => ' ', 'required' => true, 'multioptions' => array( 'vk' => '', 'fc' => 'FaceBook', 'tw' => 'Twitter', ) ) ), ) ) ), 'submit' => array( 'type' => 'Submit', 'options' => array( 'label' => '' ) ), ), ); $form = new Zend_Form(); $form->addPrefixPath('My_JQuery_Form','My/JQuery/Form'); $form->setOptions($opts); if($this->getRequest()->isPost()) { if($form->isValid($this->getRequest()->getPost())) { $values = $form->getValues(); $this->view->assign('MyFormValues',$values); } } $this->view->assign('MyForm',$form->render()); } }
/Views/scripts/form/index.phtml में एक दृश्य स्क्रिप्ट बनाएं
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title> </title> <?php print $this->JQuery(); ?> </head> <body class="ui-widget"> <h1> </h1> <?php print $this->MyForm; ?> <?php if($this->MyFormValues) { ?> <pre> <?php print_r($this->MyFormValues); ?> </pre> <?php } ?> </body> </html>
जैसा कि आप देख सकते हैं, मल्टीलेमेंट तत्व में "तत्व" विकल्प अनुभाग शामिल है, जो Zend_Form_Element के साथ संगत है।
मल्टीलेमेंट तत्व के संचालन का सिद्धांत इस प्रकार है:
- तत्वों के प्रत्येक समूह के लिए, एक Zend_Form फॉर्म बिना फॉर्म और DtDdWrapper डेकोरेटर के बनाया जाता है।
- समूह में प्रत्येक तत्व सेट एलिमेंट्स का उपयोग करके सेट किया गया है। प्रपत्र तत्व [] [group_ element] के नाम का उपयोग करें
- व्यू असिस्टेंट में आगे उपयोग के लिए फॉर्म को मल्टीएम्लेमेंट तत्व के विकल्पों में रेंडर और रखा गया है
- प्रपत्र ऑब्जेक्ट को अपने अमान्य क्लोनों के आगे उपयोग के लिए एक निजी संपत्ति में डाल दिया जाता है
- व्यू हेल्पर में, रेंडर किए गए ग्रुप फॉर्म को js वेरिएबल में डाल दिया जाता है और addJavascript के जरिए व्यू ऑब्जेक्ट में जोड़ा जाता है
- व्यू हेल्पर में, "ऐड" बटन बनाया जाता है और उस पर क्लिक को संसाधित करने के लिए js का उपयोग किया जाता है
- जब क्लिक किया जाता है, तो प्रदान किए गए फॉर्म को जेएस वेरिएबल से तत्व नामों के प्रतिस्थापन के साथ तत्व [काउंटर] [ग्रुप कोडेल] के साथ डाला जाता है
- व्यू हेल्पर तत्व समूहों और स्वयं समूहों के आने वाले मूल्यों को भी आकर्षित करता है
<?php require_once "Zend/Form/Element/Xhtml.php"; class My_JQuery_Form_Element_MultiElement extends Zend_Form_Element_Xhtml { public $helper = "multiElement"; protected $forms = array(); protected $form; protected $renderform = ''; public function __construct($spec, $options = null) { if(isset($options['elements']) && is_array($options['elements'])) { $form = new Zend_Form(array('elements'=>$options['elements'])); $form -> removeDecorator('Form'); $form -> removeDecorator('DtDdWrapper'); $form -> setElementsBelongTo($spec.'[]'); $this->renderform = $form->render(); unset($options['elements']); $this->form = $form; } parent::__construct($spec, $options); } public function isValid($value) { $this->_messages = array(); $this->_errors = array(); $this->setValue($value); $value = $this->getValue(); if(!is_array($value) && $this->isRequired()) { $this->_messages = array(' '); return false; } $result = true; if(is_array($value)) { foreach ($value as $key=>$mini_form) { if(key_exists($key,$this->forms)) { $form = $this->forms[$key]; if(!$form->isValid($mini_form)) $result = false; } } } return $result; } public function setValue($value) { if(!is_array($value)) return $this; $this->_value = $value; foreach ($value as $mini_form) { $form = clone $this->form; $this->forms[] = $form->setDefaults($mini_form); } return $this; } }
जैसा कि आप देख सकते हैं, आवश्यक विकल्प समर्थित है। यदि आवश्यक हो, तो अतिरिक्त विकल्प, फिल्टर और सत्यापनकर्ताओं के प्रसंस्करण को जोड़कर मल्टीप्लिमेंट तत्व का विस्तार किया जा सकता है
हेल्पर कोड देखें
<?php require_once "ZendX/JQuery/View/Helper/UiWidget.php"; class My_JQuery_View_Helper_MultiElement extends ZendX_JQuery_View_Helper_UiWidget { public function multiElement($id, $value = null, array $params = array()) { $js_var = $id . '_subform'; if(isset($params['renderform'])) { $this->jquery->addJavascript('var ' . $js_var . ' = ' . ZendX_JQuery::encodeJson($params['renderform']) . ';'); } $icon_delete = $this->view->formButton($id . '_delete', '');; $button_id = $id . '_add'; $button = $this->view->formButton($button_id, ''); $jquery_handler = ZendX_JQuery_View_Helper_JQuery::getJQueryHandler(); $js = array(); $js[] = sprintf('%s("#%s").next("ul").find("> li").prepend(%s("%s").click(function(){ if(confirm("%s")) %s(this).parent("li").remove(); return false; }));', $jquery_handler, $button_id, $jquery_handler, addslashes($icon_delete), '?', $jquery_handler); $js[] = sprintf('%s("#%s").click(function(){ var itr = %s(this).next("ul").find("> li").length-1; var Tmpl = %s.replace(/name=\"%s\[\]\[/g,"name=\"%s["+itr+"]["); var li = %s(this).next("ul").find("li:last").clone(true).insertBefore(%s(this) .next("ul").find("li:last")).append(Tmpl).show(); });', $jquery_handler, $button_id, $jquery_handler, $js_var, $id, $id, $jquery_handler, $jquery_handler); $this->jquery->addOnLoad(join(PHP_EOL,$js)); $xhtml = array(); $xhtml[] = '<ul>'; $attribs = array(); foreach ($params as $k=>$v) if(in_array($k,array('class','style'))) $attribs[$k] = $v; foreach ($params['forms'] as $key=>$form) { $form -> setElementsBelongTo($id . '['.$key.']'); $xhtml[] = '<li' . $this->_htmlAttribs($attribs) . '>' . $form->render() . '</li>'; } if(isset($attribs['style'])) $attribs['style'] .= ';display:none'; else $attribs['style'] = 'display:none'; $xhtml[] = '<li' . $this->_htmlAttribs($attribs) . '></li>'; $xhtml[] = '</ul>'; return $button . join(PHP_EOL,$xhtml); } }
एक साफ पदानुक्रमित रूप में मान प्राप्त किए जाते हैं
[firstname] => [lastname] => [items] => Array ( [2] => Array ( [name] => [type] => red [price] => 1000 ) [3] => Array ( [name] => [type] => blue [price] => 2000 ) ) [logons] => Array ( [0] => Array ( [login] => username [passw] => qwerty [type] => vk ) )
दुर्भाग्य से, आप एक फ़ाइल समूह को एक तत्व समूह में नहीं जोड़ सकते क्योंकि यह बेलॉन्गो का समर्थन नहीं करता है। मैंने फ़ाइल डेकोरेटर में अपना समर्थन जोड़ने की कोशिश की, लेकिन चर $ _FILES में बहुआयामी सरणियों के प्रसंस्करण की कमी के कारण Zend_File_Transfer_Adapter में समस्याओं में भाग गया।
आप [बिना] setBelongTo में एक उपसर्ग बनाने की कोशिश कर सकते हैं और फ़ाइल सरणी को उन तत्वों के समूह से अलग से संसाधित कर सकते हैं जो वे फ़ाइल तत्व के बजाय किसी प्रकार के Ajax फ़ाइल अपलोडर का उपयोग करते हैं या उपयोग करते हैं।
आप
यहां से पूरी तरह से काम करने का उदाहरण डाउनलोड कर सकते
हैं।