Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zend2 setting field to not be required without losing element's default input filter spec

Using ZF2, I wrote a custom form Element and include it on a bunch of forms. The problem is that if I specify that I don't want the form element to be required, I lose the default validators on the element.

class MyForm extends Zend\Form\Form implements Zend\InputFilter\InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct("my-form");
        $this
        ->add(array(
            'type' => 'Me\Custom\EmailList',
            'name' => 'emails',
            'options' => array(
                'label' => _t('Email List'),
            ),
        ));
    }

    public function getInputFilterSpecification()
    {
        return array(
            'emails' => array(
                'required' => false,
             ),
        ));
    }
}

The "EmailList" element is a simple text field that accepts a comma-separated list of email addresses.

class EmailList extends \Zend\Form\Element\Email
{
    protected $attributes = array(
        'type' => 'email',
        'multiple' => true,
    );
    public function getInputSpecification()
    {
        $this->getEmailValidator()
            ->setMessage('"%value%" is not a valid email address');

        $validator = $this->getValidator();
        if ($validator instanceof ExplodeValidator) {
            $validator->setValueDelimiter(', ');
        }

        return array(
            'name' => $this->getName(),
            'required' => true,
            'validators' => array(
                $validator,
            ),
        );
    }
}

So, in my MyForm class, it appears that by including "emails" in getInputSpecification(), the default validator on EmailList is completely wiped out and never used.

How do I go about setting the required flag to false and maintain the element's default validator?

Note, this custom field is used in a bunch of forms and most of the time is required, which is why its default specification includes setting the required flag to true.

Thanks

like image 346
jbarreiros Avatar asked Feb 19 '14 23:02

jbarreiros


1 Answers

So you want the email field to be optional, but if populated, for it to use your validator?

Assuming I've understood that problem correctly, your code works just fine for me (on ZF 2.2.5) with one very small change:

class EmailList extends \Zend\Form\Element\Email
{
    protected $attributes = array(
        'type' => 'text', // <- I changed type from 'email' to 'text'
        'multiple' => true,
    );

[...]

HTML type="email" is one of the field types added in HTML5, and (in Webkit browsers at least) this triggers some client-side validation in the browser itself. One thing the browser will do with a field of this type is remove any spaces. Your form then fails to validate because you want , (comma space) as the separator. By changing the type to text the browser will treat it as a plain old text field, and ZF will handle all the validation server-side.

If this is the problem, you'd probably find that setting the value delimiter to , (or not setting it at all) would fix the issue as well.

If that doesn't fix it, verify that the app is going into the if ($validator instanceof ExplodeValidator) { condition. You can also try taking a look at the validators attached to the form element from the controller using:

var_dump($form->getInputFilter()->get('emails')->getValidatorChain());
like image 77
Tim Fountain Avatar answered Oct 20 '22 03:10

Tim Fountain