在Radio或Checkbox项目下嵌套Fieldsets:Zend Framework 2

时间:2013-05-16 11:22:19

标签: forms checkbox radio-button zend-framework2 fieldset

我想在每个收音机/复选框项下创建一个字段集。

例如

Which animals do you like:

[x] Cats

    [Fieldset of cat related questions]

[ ] Dogs

    [Fieldset of dog related questions]

...

我可以轻松创建Fieldsets和Forms,但将它们嵌套在每个项目下会让我感到头痛。

最终我想到了这样的事情:

 $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'
        )
    ));

1 个答案:

答案 0 :(得分:-1)

好的,我设法使用一些黑客来解决这个问题,但它确实有效。

TestForm.php(注意元素中的其他属性('parent'和'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',
        ),
    ));
}
}

然后扩展Zend \ Form \ View \ Helper \ FormMultiCheckbox并覆盖RenderOptions方法(注意新的optionSpec'parent')这基本上创建了一个标签,例如{# cat #}之后父元素:

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

扩展并覆盖了Zend \ Form \ View \ Helper \ FormRow渲染方法,除了返回方法外,这是相同的:

    ..... 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);

最后扩展并覆盖了Zend \ Form \ View \ Helper \ FormCollection的渲染方法,并更改了元素foreach循环,如果元素是数组,则基本上覆盖标记,因此具有ChildOf标记。然后清理标签:

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

这(虽然丑陋)产生了预期的结果,也因为我们只是在玩渲染,验证和表单创建都没有受到影响。

一切顺利, Aborgrove