Nested fields in the Radio or Check box: Zend Framework 2

I would like to create a set of fields under each radio / checkbox element.

eg

Which animals do you like: [x] Cats [Fieldset of cat related questions] [ ] Dogs [Fieldset of dog related questions] 

...

I can create Fieldsets and Forms with ease, but nesting them under each element causes me some headaches.

In the end, I meant something like this:

  $this->add(array( 'type' => 'Zend\Form\Element\Radio', 'name' => 'profile_type', 'options' => array( 'label' => 'Which animals do you like:', 'label_attributes' => array('class'=>'radio inline'), 'value_options' => array( '1' =>'cats', 'fieldsets' => array( array( 'name' => 'sender', 'elements' => array( array( 'name' => 'name', 'options' => array( 'label' => 'Your name', ), 'type' => 'Text' ), array( 'type' => 'Zend\Form\Element\Email', 'name' => 'email', 'options' => array( 'label' => 'Your email address', ), ), ), )), '2'=>'dogs', 'fieldsets' => array( array( 'name' => 'sender', 'elements' => array( array( 'name' => 'name', 'options' => array( 'label' => 'Your name', ), 'type' => 'Text' ), array( 'type' => 'Zend\Form\Element\Email', 'name' => 'email', 'options' => array( 'label' => 'Your email address', ), ), ), )) ), ), 'attributes' => array( 'value' => '1' //set checked to '1' ) )); 
+4
source share
1 answer

Well I managed to get around this problem using a bit of hacking, but it works.

TestForm.php (note the additional attributes in the elements ('parent' and 'childOf')

 class TestForm extends Form { public $user_agent; public $user_ip; public function __construct($name = null) { // we want to ignore the name passed parent::__construct('profile'); $this->setAttributes(array( 'method'=>'post', 'class'=>'form-horizontal', )); $this->add(array( 'type' => 'Zend\Form\Element\Radio', 'name' => 'profile_type', 'options' => array( 'label' => 'Which animals do you like:', 'label_attributes' => array('class'=>'radio inline'), 'value_options' => array( array('label' =>'cats', 'value'=>1, 'parent'=>'cat'), array('label'=>'dogs', 'value'=>2, 'parent'=>'dog'), ), ), 'attributes' => array( 'value' => '1' //set checked to '1' ) )); $this->add(array( 'type' => 'Text', 'name' => 'name', 'attributes' => array( 'childOf' => 'cat', ), 'options' => array( 'label' => 'Your name', ), )); $this->add(array( 'type' => 'Zend\Form\Element\Email', 'name' => 'email', 'attributes' => array( 'childOf' => 'dog', ), 'options' => array( 'label' => 'Your email address', ), )); } } 

Then extended Zend \ Form \ View \ Helper \ FormMultiCheckbox and overwritten the RenderOptions method (note the new optionSpec parent parameter), this basically creates a tag, for example {# cat #} after the parent element:

 protected function renderOptions(MultiCheckboxElement $element, array $options, array $selectedOptions, array $attributes) { $escapeHtmlHelper = $this->getEscapeHtmlHelper(); $labelHelper = $this->getLabelHelper(); $labelClose = $labelHelper->closeTag(); $labelPosition = $this->getLabelPosition(); $globalLabelAttributes = $element->getLabelAttributes(); $closingBracket = $this->getInlineClosingBracket(); if (empty($globalLabelAttributes)) { $globalLabelAttributes = $this->labelAttributes; } $combinedMarkup = array(); $count = 0; foreach ($options as $key => $optionSpec) { $count++; if ($count > 1 && array_key_exists('id', $attributes)) { unset($attributes['id']); } $value = ''; $parent = ''; $label = ''; $inputAttributes = $attributes; $labelAttributes = $globalLabelAttributes; $selected = isset($inputAttributes['selected']) && $inputAttributes['type'] != 'radio' && $inputAttributes['selected'] != false ? true : false; $disabled = isset($inputAttributes['disabled']) && $inputAttributes['disabled'] != false ? true : false; if (is_scalar($optionSpec)) { $optionSpec = array( 'label' => $optionSpec, 'value' => $key ); } if (isset($optionSpec['value'])) { $value = $optionSpec['value']; } if (isset($optionSpec['parent'])) { $parent = $optionSpec['parent']; } if (isset($optionSpec['label'])) { $label = $optionSpec['label']; } if (isset($optionSpec['selected'])) { $selected = $optionSpec['selected']; } if (isset($optionSpec['disabled'])) { $disabled = $optionSpec['disabled']; } if (isset($optionSpec['label_attributes'])) { $labelAttributes = (isset($labelAttributes)) ? array_merge($labelAttributes, $optionSpec['label_attributes']) : $optionSpec['label_attributes']; } if (isset($optionSpec['attributes'])) { $inputAttributes = array_merge($inputAttributes, $optionSpec['attributes']); } if (in_array($value, $selectedOptions)) { $selected = true; } $inputAttributes['value'] = $value; $inputAttributes['checked'] = $selected; $inputAttributes['disabled'] = $disabled; $input = sprintf( '<input %s%s', $this->createAttributesString($inputAttributes), $closingBracket ); if (null !== ($translator = $this->getTranslator())) { $label = $translator->translate( $label, $this->getTranslatorTextDomain() ); } $tag = ($parent != '')? "{#*".$parent."*#}": ""; $label = $escapeHtmlHelper($label); $labelOpen = $labelHelper->openTag($labelAttributes); $template = $labelOpen . '%s%s%s' . $labelClose; switch ($labelPosition) { case self::LABEL_PREPEND: $markup = sprintf($template, $label, $input, $tag); break; case self::LABEL_APPEND: default: $markup = sprintf($template, $input, $label, $tag); break; } $combinedMarkup[] = $markup; } return implode($this->getSeparator(), $combinedMarkup); } 

The extended and overwritten rendering method of Zend \ Form \ View \ Helper \ FormRow is the same, with the exception of returning the method:

  ..... more code ..... $child_of = $element->getAttribute('childOf'); if($child_of != '') { return array($child_of => sprintf('<div class="control-group%s">%s</div>', $status_type, $markup)); } return sprintf('<div class="control-group%s">%s</div>', $status_type, $markup); 

And finally, expanded and rewritten the rendering method of Zend \ Form \ View \ Helper \ FormCollection and changed the foreach loop of the element, basically rewriting the tags if that element is an array and therefore has a ChildOf tag. Then clear the tags:

 foreach ($element->getIterator() as $elementOrFieldset) { if ($elementOrFieldset instanceof FieldsetInterface) { $markup .= $fieldsetHelper($elementOrFieldset); } elseif ($elementOrFieldset instanceof ElementInterface) { $elementString = $elementHelper($elementOrFieldset); if(!is_array($elementString)) { $markup .= $elementString; } // is child of another element else { foreach($elementString as $key => $value) { $match = "{#*".$key."*#}"; $replacement = $value.$match; $markup = str_replace($match, $replacement, $markup); } } } } $pattern = '/[{#\*]+[a-z0-0A-Z]*[\*#}]+/'; $markup = preg_replace($pattern, '', $markup); 

This (albeit ugly) gives the desired results, also because we just play with the rendering, validation and creation of the form intact.

All the best, Aborgrove

-1
source

Source: https://habr.com/ru/post/1481156/


All Articles