Zend_Form: Element should only be required if a checkbox is checked
Asked Answered
C

7

11

I've got a Form where the user can check a checkbox "create new address" and can then fill out the fields for this new address in the same form.

Now I want to validate the fields of this new address ONLY if the checkbox has been checked. Otherwise, they should be ignored.

How can I do that using Zend_Form with Zend_Validate?

Thanks!

Collins answered 16/9, 2009 at 9:25 Comment(0)
E
7

I think that the best, and more correct way to do this is creating a custom validator.

You can do this validator in two different ways, one is using the second parameter passed to the method isValid, $context, that is the current form being validated, or, inject the Checkbox element, that need to be checked for validation to occur, in the constructor. I prefer the last:

<?php
class RequiredIfCheckboxIsChecked extends Zend_Validate_Abstract {

    const REQUIRED = 'required';

    protected $element;

    protected $_messageTemplates = array(
        self::REQUIRED => 'Element required'
    );

    public function __construct( Zend_Form_Element_Checkbox $element )
    {
        $this->element = $element;
    }

    public function isValid( $value )
    {
        $this->_setValue( $value );

        if( $this->element->isChecked() && $value === '' ) {
            $this->_error( self::REQUIRED );
            return false;
        }

        return true;
    }

}

Usage:

class MyForm extends Zend_Form {

    public function init()
    {
        //...

        $checkElement = new Zend_Form_Element_Checkbox( 'checkbox' );
        $checkElement->setRequired();

        $dependentElement = new Zend_Form_Element_Text( 'text' );
        $dependentElement->setAllowEmpty( false )
            ->addValidator( new RequiredIfCheckboxIsChecked( $checkElement ) );

        //...
    }

}

I have not tested the code, but I think it should work.

Ezekiel answered 30/3, 2012 at 1:7 Comment(0)
S
2

I didn't actually run this, but it should work within reason. I've done something similar before that worked, but couldn't remember where the code was.

<?php

class My_Form extends Zend_Form
{
  public function init()
  {
    $checkbox = new Zend_Form_Element_Checkbox("checkbox");
    $checkbox->setValue("checked");

    $textField = new Zend_Form_Element_Text("text");

    $this->addElements(array("checkbox", "text"));

    $checkbox = $this->getElement("checkbox");

    if ($checkbox->isChecked() )
    {
       //get textfield
       $textField = $this->getElement("text");

       //make fields required and add validations to it.
       $textField->setRequired(true);
    }

  }

}
Silda answered 17/9, 2009 at 4:36 Comment(0)
M
2

Here's what I do if I need to validate multiple elements against each other

$f = new Zend_Form();

if($_POST && $f->isValid($_POST)) {
  if($f->checkbox->isChecked() && strlen($f->getValue('element')) === 0) {
    $f->element->addError('Checkbox checked, but element empty');
    $f->markAsError();
  }

  if(!$f->isErrors()) {
    // process
    ...
    ...
  }
}
Meenen answered 17/9, 2009 at 14:36 Comment(0)
C
1

I've been wondering how to do that in ZF as well, though never had to implement such form feature.

One idea that comes to mind is to create a custom validator that accepts the checkbox field as a parameter, and run it in a validator chain, as documented. If the checkbox is checked, validator could return failure. Then you can check whether all validations failed and only then treat form as having failed validation.

That level of customization of form validation could be inconvenient, so maybe using form's isValidPartial method would be better.

Cheekbone answered 16/9, 2009 at 9:48 Comment(0)
D
1

I created a custom validator that will make your element required based on the value of another zend form element.

Here's the full code. I hope this helps someone.

The idea is to create a custom validator and pass in the name of the conditional element and the value of that conditional element into the constructor. Zend_Validor's isValid method already has access to the value of the element you are attaching the validtor to along with all the form element names and values.

So, inside the isValid method you have all the information you need to determine if your form element should be a required element.

Drawshave answered 26/7, 2013 at 0:21 Comment(1)
Welcome to Stack Overflow. Please summarise the link in your answer; that way, if the link goes stale the answer won't be completely useless.Mortar
I
1

On Zend 1 extend the isValid method, where you set required depending on posted data for example:

    public function isValid($data)
    {
        if (!empty($data['companyCar'])) {
            $this->getElement('carValue')->setRequired(true);
        }

        return parent::isValid($data);
    }
Idaidae answered 30/12, 2016 at 9:58 Comment(0)
S
0

Thank you JCM for your good solution.

However 2 things I've noticed:

  • The isValid method of your validator has to return true in case of success.
  • The validator will not be executed during form validation without pass the allowEmpty option to false to the text field.
Schmit answered 15/5, 2013 at 9:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.