zend-framework2zend-formcode-reusezend-form-elementzend-form-fieldset

How to set the type of an element in a Fieldset child class in Zend Framework 2?


I have two very similar Fieldsets MyFooFieldset and MyBarFieldset. In order to avoid code duplication, I created an AbstractMyFieldset, moved the whole code there, and want to handle the differences in the init() methods of the concrete classes:

AbstractMyFooFieldset

namespace My\Form\Fieldset;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
abstract class AbstractMyFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function init()
    {
        $this->add(
            [
                'type' => 'multi_checkbox',
                'name' => 'my_field',
                'options' => [
                    'label_attributes' => [
                        'class' => '...'
                    ],
                    'value_options' => $this->getValueOptions()
                ]
            ]);
    }
    public function getInputFilterSpecification()
    {
        return [...];
    }
    protected function getValueOptions()
    {
        ...
        return $valueOptions;
    }
}

MyFooServerFieldset

namespace My\Form\Fieldset;
use Zend\Form\Fieldset;
class MyFooServerFieldset extends AbstractMyFieldset
{
    public function init()
    {
        parent::init();
        $this->get('my_field')->setType('radio'); // There is not method Element#setType(...)! How to do this?
        $this->get('my_field')->setAttribute('required', 'required'); // But this works.
    }
}

I want to set the type and some other configurations for the element, e.g. the type and the required attribute. Setting attributes seems to be OK, at least I can set the required attribute. But I cannot set the type -- the Element#setType(...) is not there.

How to set the type of a Zend\Form\Element, after it has been added?


Solution

  • There is no way to set the type of an element as each element has its own type and element class defined. In your AbstractMyFieldset, see the "Type" key within your init(). You tell the form to add the MultiCheckbox element class and want to change the class to another one. So you need to either remove the default and copy it's attributes and options over to a newly added Zend Form element.

    Another option is to use the base Zend\Form\Element class you can overwrite the attributes and set the type attribute. ->setAttribute('type', 'my_type') but ur missing all the benefits of the default Zend2 form classes. Especially as the default InArray validator for Zend\Form\Element\Radio or the Zend\Form\Element\MultiCheckbox.

    Or you should just consider making an abstractFieldSet for the both fieldsets and define how they get their value options and reuse that. Like:

    abstract class AbstractFieldSet extends Fieldset {
        public function addMyField($isRadio = false)
        {
            $this->add([
                'type' => $isRadio ? 'radio' : 'multi_checkbox',
                'name' => 'my_field',
                'options' => [
                    'value_options' => $this->getValueOptions()
                ]
            ]);
        }
    
        protected function getValueOptions()
        {
            // ..
            return $valueOptions
        }
    }
    
    class fieldSet1 extends AbstractFieldSet {
        public function init()
        {
            $this->addMyField(false);
        }
    }
    
    class fieldSet2 extends AbstractFieldSet {
        public function init()
        {
            $this->addMyField(true);
        }
    }