views:

144

answers:

2

Is there any good solution for the following requirement:

An Form with one field for the zip code and default validators like (number, length 4..). After submit, the form is checked against an database.

If the zip code is not unique we have to ask for an city.

Examples

Case 1: Submited zip code is unique in database : everything ok --> process form

Case 2: Submited zip code is not unique, we have to add an second field city to the form --> back to form

We want to handle this in an generic way (not inside an controller). We need this logic for a lot of forms. First thought was to add it to the isValid() to every form or write an validator with logic to add fields to the form (?). Subforms are not possible for us, because we altough need this for different fields (example. Name and Street..)

A: 

You will probably need a Javascript form validator for that. In the submit function perform an AJAX call to check if the zipcode is unique. If not, show an extra city field.

But you still have to perform the validation server side: never trust user input, even if it's validated on the client side.

zwip
+2  A: 

Currently I'm using isValid method inside my forms for an User Form to verify the password and confirm password field. Also, when the form is displayed in a New Action, there are no modifications, but when displayed in an Edit Action, a new field is added to the form.

I think that is a good option work on the isValid method and add the field when the validation return false, and if you want something more maintainable, you should write your own validatator for that purpose.

Take a look at my code:

class Admin_Form_User extends Zf_Form 
{
    public function __construct($options = NULL)
    {
        parent::__construct($options);
        $this->setName('user');

        $id = new Zend_Form_Element_Hidden('id');

        $user = new Zend_Form_Element_Text('user');
        $user->setLabel('User:')
        ->addFilter('stripTags')
        ->addFilter('StringTrim')
        ->setAllowEmpty(false)
        ->setRequired(true);

        $passwordChange = new Zend_Form_Element_Radio('changePassword');
        $passwordChange->setLabel('Would you like to change the password?')
        ->addMultiOptions(array(1 => 'Sim', 2 => 'Não'))
        ->setValue(2)
        ->setSeparator('');

        $password = new Zend_Form_Element_Password('password');
        $password->setLabel('Password:')
        ->addFilter('stripTags')
        ->addFilter('StringTrim')
        ->setRequired(true);

        $confirm_password = new Zend_Form_Element_Password('confirm_password');
        $confirm_password->setLabel('Confirm the password:')
        ->addFilter('stripTags')
        ->addFilter('StringTrim')
        ->addValidator('Identical')
        ->setRequired(true);

        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setLabel('Save');

        $this->addElements(array($id,$name,$lastname,$group,$user,$passwordChange,$password,$confirm_password,$submit));

        $this->addDisplayGroup(array('password','confirm_password'),'passwordGroup');
        $this->submit->setOrder(8);

        $this->setDisplayGroupDecorators(array(
            'FormElements',
            array('HtmlTag', array('tag' => 'div','id' => 'div-password'))
            )
        );

        $passwordChange->clearDecorators();

    }

    public function addPasswordOption()
    {
        $this->changePassword->loadDefaultDecorators();

        $this->getDisplayGroup('passwordGroup')
        ->addDecorators(array(
            array('HtmlTag', array('tag' => 'div','id' => 'div-password'))
            )
        );

        $this->password->setRequired(false);
        $this->confirm_password->setRequired(false);
    }

    public function setPasswordRequired($flag = true)
    {
        $this->password->setRequired($flag);
        $this->confirm_password->setRequired($flag);
    }

    public function isValid($data)
    {
        $confirm = $this->getElement('confirm_password');
        $confirm->getValidator('Identical')->setToken($data['password']);
        return parent::isValid($data);
    }

}

So, in my controller:

public function newAction()
    {
        $this->view->title = "New user";
        $this->view->headTitle($this->view->title, 'PREPEND');

        $form = $this->getForm();

        if($this->getRequest()->isPost()) 
        {
            $formData = $this->_request->getPost();

            if($form->isValid($formData))
            {
                $Model = $this->getModel();
                $id = $Model->insert($formData);

                $this->_helper->flashMessenger('The user data has beed updated.');
                $this->_helper->redirector('list');
            }
        }

        $this->view->form = $form;
    }

    public function editAction()
    {       
        $this->view->title = "Edit user";
        $this->view->headTitle($this->view->title, 'PREPEND');

        $id = $this->getRequest()->getParam('id');

        $form = $this->getForm();

        // Add yes or no password change option
        $form->addPasswordOption();

        $Model = $this->getModel();

        if($this->getRequest()->isPost()) 
        {
            $formData = $this->getRequest()->getPost();

            // Change password?
            if($formData['changePassword'] == 2) $form->setPasswordRequired(false);

            if($form->isValid($formData)) 
            {
                $Model->update($formData);

                $this->_helper->flashMessenger('The user data has beed updated.');
                $this->_helper->redirector('list');
            } 

        }

        $data = $Model->getById($id)->toArray();

        $form->populate($data);

        $this->view->form = $form;
    }
Keyne