Search code examples
zend-framework2zend-framework3zend-inputfilterzend-form-fieldset

zf add inputfilter for a new fieldset element in the form class


In zend framework, how do I add an inputfilter for a new form element in a fieldset with the code in the form? In the following case, I've defined a set of common form elements and an inputfilter for those elements in a fieldset class, and add the fieldset to the form. After that, I add one or more new form elements to the fieldset in the form code (I'm doing it in the form and not in the fieldset to prepare to add elements dynamically by form factory). What I'm having trouble with is adding new inputfilter definitions for the additional elements.

in my fieldset:

class myFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function init()
    {

        // add form elements

    }

    public function getInputFilterSpecification()
    {

        $inputFilter['myFormElement'] = [
            'required' => true,
            'filters'  => [[ ... ],],
            'validators' => [[ ... ],],             
            'allow_empty' => false,
            'continue_if_empty' => false,
        ];

        // more filters

        return $inputFilter;

    }   

}

in my form:

class myForm extends Form
{

    public function __construct()
    {
        // ...

        // add elements from fieldset
        $this->add([
            'name' => 'myFieldset',
            'type' => 'Application\Form\Fieldset\myFieldset',
            'options' => [
                'use_as_base_fieldset' => true,
            ],
        ]);

        // add new element
        $myFieldset = $this->get('myFieldset');
        $myFieldset->add([
            'name' => 'additionalElement',
            'type' => 'Zend\Form\Element\ ... ',
            'attributes' => [],
            'options' => [],
        ]);

        // update inputfilter
        $input = new Input('additionalElement');
        $input->setRequired(false);

        $currentInputFilter = $this->getInputFilter();
        $currentInputFilter->add($input); 
        $this->setInputFilter($currentInputFilter);

        // submit buttons

    }

}

In this example, the additional element gets added to the fieldset, but I've got the code wrong to add new definitions to the inputfilter.


Solution

  • You need to get the Input Filter of the Fieldset and not of the form class. For this Zend Framework holds the InputFilterProviderFieldset class, from which you should inherit your fieldset. The InputFilterProviderFieldset class comes with getter and setter methods for modifying your input filter specifications at the runtime. The following code is not tested, but should work.

    namesapce Application\Form\MyFieldset;
    
    use Zend\Form\InputFilterProviderFieldset;
    
    class MyFieldset extends InputFilterProviderFieldset
    {
        public function init()
        {
            $this->add([
                'name' => 'element1',
                'type' => Text::class,
                'attributes' => [
                    ...
                ],
                'options' => [
                    ...
                ],
            ]);
        }
    }
    

    With using the InputFilterProviderFieldset class, your form class should look like this.

    namespace Application\Form;
    
    use Zend\Form\Form;
    
    class YourForm extends Form
    {
        public function __construct(string $name, array $options = [])
        {
            // definition of your fieldset must use the input_filter_spec key
            $this->add([
                'name' => 'myFieldset',
                'type' => 'Application\Form\Fieldset\myFieldset',
                'options' => [
                    'use_as_base_fieldset' => true,
                    'input_filter_spec' => [
                        'element1' => [
                            'required' => true,
                            'filters' => [
                                ...
                            ],
                            'validators' => [
                                ...
                            ],
                        ],
                    ],
                ],
            ]);
    
            // add a new element to the fieldset
            $this->get('myFieldset')->add([
                'name' => 'element2',
                'type' => Text::class,
                'attributes' => [
                    ...
                ],
                'options' => [
                    ...
                ],
            ]);
    
            // Update the input filter of the fieldset
            $myFieldsetFilterSpec = $this->get('myFieldset')->getInputFilterSpecification();
            $myNewFieldsetFilterSpec = array_merge(
                $myFieldsetFilterSpec,
                [
                    'element2' => [
                        'required' => false,
                    ],
                ],
            );
    
            // set the new filter specs for your fieldset
            $this->get('myFieldset')->setInputFilterSpecification($myNewFieldsetFilterSpec);
        }
    }
    

    As you can see Zend Framework brings all the stuff you need for solving your issue. I hope this approach will help you.