Question

So I have a "simple" form

class SiteAddForm extends Form
{
    public function __construct()
    {
        parent::__construct('add_site_form');

        $site = new SiteFieldSet();
        $this->add($site);
    }

    public function getTemplate()
    {
        return 'site_add.phtml';
    }
}

The form it self does nothing. It adds a field_set and returns a template name.

The SiteFieldSet looks likes:

class SiteFieldSet
    extends FieldSet
    implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('site');

        $name = new Text('name');
        $this->add($name);

        $domains = new Collection('domains');
        $domains->setTargetElement(new DomainFieldSet())
            ->setShouldCreateTemplate(true);
        $this->add($domains);
    }

    public function getTemplate()
    {
        return 'site.phtml';
    }

    /**
     * Should return an array specification compatible with
     * {@link Zend\InputFilter\Factory::createInputFilter()}.
     *
     * @return array
     */
    public function getInputFilterSpecification()
    {
        return [
            'name' => [
                'required' => true,
                'validators' => [
                    new StringLength([
                        'min' => 200,
                    ])
                ]
            ],
            'domains' => [
                'required' => true,
            ],
        ];
    }
}

It adds a text and collection element to the fieldset. The field set implements InputFilterProviderInterface to validate the data thrown into it.

The name must be at least 200 chars (for testing) and the collection is required.

But now comes my problem. With the field set that is thrown into the collection, code:

class DomainFieldSet
    extends FieldSet
    implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('domain');

        $host = new Url('host');
        $this->add($host);

        $language = new Select('language', [
            'value_options' => [
                'nl_NL' => 'NL',
            ],
        ]);
        $this->add($language);

        $theme = new Select('theme', [
            'value_options' => [
                'yeti' => 'Yeti',
            ]
        ]);
        $this->add($theme);
    }

    public function getTemplate()
    {
        return 'domain.phtml';
    }

    /**
     * Should return an array specification compatible with
     * {@link Zend\InputFilter\Factory::createInputFilter()}.
     *
     * @return array
     */
    public function getInputFilterSpecification()
    {
        return [
            'host' => [
                'required' => true,
                'validators' => [
                    new StringLength([
                        'min' => 200,
                    ])
                ]
            ],
            'language' => [
                'required' => true,
            ],
            'theme' => [
                'required' => true,
            ],
        ];
    }
}

Again nothing special. There are now three elements defined host, theme & language. Again the field set implements InputFilterProviderInterface. So there must be an getInputFilterSpecification in the class.

When I fill in the form site[name] = "test" site[domains][0][host] = 'test' site[domains][0][theme] = 'yeti' site[domains][0][language] = 'nl_NL'

It gives an error for site[name] saying it must be atleast 200 chars, so validations "works" But it should also give an error on site[domains][0][host] that it needs to be atleast 200 chars (code was copy pasted, and the use is correct).

So why doesn't the validation kicks in, and or how can I solve the issue so a element/field set inside a collection is properly validated

Was it helpful?

Solution

Try using setValidationGroup in the form __construct method

like:

  public function __construct()
  {
    $this->add(array(
            'type' => 'Your\Namespace\SiteFieldSet',
            'options' => array(
                    'use_as_base_fieldset' => true,
            ),
    ));


    $this->setValidationGroup(array(
            'site' => array(
                'domain' => array(
                    'host',
                    'language',
                    'theme',
                ),
            ),
    ));

    }

or this may also work...

  $this->setValidationGroup(FormInterface::VALIDATE_ALL);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top