zend-framework2fieldsetzend-form2

How to add class to fieldset?


I have a form in ZF2 with the following element being added:

$this->add(array(
    'name' => 'animals',
    'type' => 'radio',
    'attributes' => array(
        'id' => 'animals',
        'class' => 'form-control',
    ),
    'options' => array(
        'label' => 'Favourite animal',
        'options' => array(
            'cat' => 'Cat',
            'dog' => 'Dog',
            'fish' => 'Fish',
        ),
    ),
));

And in my view script I have the folloing line:

<?php echo $this->formrow($form->get('animals')); ?>

Which is generating the following html:

<fieldset>
    <legend>Favourite Animal</legend>
    <label><input type="radio" name="animals" id="animals" class="form-control input-error" value="cat">Cat</label>
    <label><input type="radio" name="animals" class="form-control input-error" value="dog">Dog</label>
    <label><input type="radio" name="animals" class="form-control input-error" value="fish">Fish</label>
</fieldset>

How do I add a class to the fieldset?

I have tried adding the following to the options array, the attributes array, and as an option to the main array but it is not adding the class to the fieldset:

'fieldset_attributes' => array(
    'class' => 'form-group',
),

[edit]

Looking into the code (\Zend\Form\View\Helper\FormRow::render) I've found this:

...
// Multicheckbox elements have to be handled differently as the HTML standard does not allow nested
// labels. The semantic way is to group them inside a fieldset
if ($type === 'multi_checkbox'  || $type === 'radio' || $element instanceof MonthSelect ) {
    $markup = sprintf('<fieldset><legend>%s</legend>%s</fieldset>', $label, $elementString);
} 
...

Which means the only way to add a class to the fieldset (or legend if you wanted) is to extend the view helper.


Solution

  • I followed the answer as posted here (https://stackoverflow.com/a/27273068/351785).

    From the answer (modified to suit my requirements):

    Create the Application\Form\View\Helper\FormRow.php helper class like below:

    <?php
    /**
     * Extend zend form view helper formrow to allow class to be added to fieldset / legend
     */
    namespace Application\Form\View\Helper;
    use Zend\Form\View\Helper\FormRow as ZendFormRow;
    
    class FormRow extends ZendFormRow
    {
    
        /**
         * Utility form helper that renders a label (if it exists), an element and errors
         *
         * @param  ElementInterface $element
         * @throws \Zend\Form\Exception\DomainException
         * @return string
         */
        public function render(\Zend\Form\ElementInterface $element)
        {
            //... other code here
    
                // Multicheckbox elements have to be handled differently as the HTML standard does not allow nested
                // labels. The semantic way is to group them inside a fieldset
                if ($type === 'multi_checkbox'
                    || $type === 'radio'
                    || $element instanceof MonthSelect
                ) {
                    $fieldset_class = $legend_class = '';
                    if($class = $element->getOption('fieldset_class')) {
                        $fieldset_class = sprintf(' class="%s"', $class);
                    }
                    if($class = $element->getOption('legend_class')) {
                        $legend_class = sprintf(' class="%s"', $class);
                    }
                    $markup = sprintf(
                        '<fieldset%s><legend%s>%s</legend>%s</fieldset>',
                        $fieldset_class,
                        $legend_class,
                        $label,
                        $elementString);
                }
            //... other code here
    
            return $markup;
        }
    
    }
    

    And override the factory in the onBootstrap() method of the Module.php file like below:

    namespace Application;
    
    use Zend\Mvc\MvcEvent;
    use Zend\View\HelperPluginManager;
    
    class Module
    {
        /**
         * On bootstrap for application module.
         *
         * @param  MvcEvent $event
         * @return void
         */
        public function onBootstrap(MvcEvent $event)
        {
            $services = $event->getApplication()->getServiceManager();
    
            // The magic happens here
            $services->get('ViewHelperManager')->setFactory('formrow', function (HelperPluginManager $manager) {
                return new \Application\Form\View\Helper\FormRow();
            });
        }
    }
    

    And add the classes as such:

    $this->add(array(
        'name' => 'animals',
        'type' => 'radio',
        'attributes' => array(
            'id' => 'animals',
            'class' => 'form-control',
        ),
        'options' => array(
            'label' => 'Favourite animal',
            'fieldset_class' => 'form-group', //<== this
            'legend_class' => 'form-legend',  //<== and this
            'options' => array(
                'cat' => 'Cat',
                'dog' => 'Dog',
                'fish' => 'Fish',
            ),
        ),
    ));