Why is onValidate event called before validation?

Notice: This thread is very old.
MartyIX
Member | 217
+
0
-

Hi,

I have a form and the form controls that have validation rules. I have a validateForm handler and in that handler I need to know if the whole form is valid (there's no violation of form controls' validation rules) or not.

Example:

public function createForm() {
    $form = new Form;
    $form->addText('name', 'Name:');
    $form->addText('age', 'Age:')
       ->addRule(Form::INTEGER, 'Your age must be an integer.')
       ->addRule(Form::RANGE, 'You must be older 18 years and be under 120.', array(18, 120));
    $form->addPassword('password', 'Password:')
       ->addRule(Form::MIN_LENGTH, 'Your password has to be at least %d long', 3);
    $form->onValidate[] = callback($this, 'validateForm');
}

// The problem is that I don't know if the form is otherwise valid or not.
public function validateForm($form)
{
     if ($isFormValid) {   // non-existent variable; just a demonstration
         // do some stuff
     }

     //
     // WORKAROUND BELOW (copied from Nette)
     //

     $isValid = true;

     foreach ($form->getControls() as $control) {
            if (!$control->getRules()->validate()) {
                    $isValid = false;
            }
     }

     if ($isValid) {
         // do some stuff
     }

}

I read the Nette source codes and it is not possible to what I need without copying a part of Nette source code.

--

Nette souce code: https://api.nette.org/…ner.php.html#148

141:     /**
142:      * Performs the server side validation.
143:      * @return void
144:      */
145:     public function validate()
146:     {
147:         $this->valid = TRUE;
148:         $this->onValidate($this);
149:         foreach ($this->getControls() as $control) {
150:             if (!$control->getRules()->validate()) {
151:                 $this->valid = FALSE;
152:             }
153:         }
154:     }

Partial solution: It would be much nicer if the Nette would do something like this:

141:     /**
142:      * Performs the server side validation.
143:      * @return void
144:      */
145:     public function validate()
146:     {
147:         $this->valid = TRUE;
148:
149:         foreach ($this->getControls() as $control) {
150:             if (!$control->getRules()->validate()) {
151:                 $this->valid = FALSE;
152:             }
153:         }

             $this->onValidate($this, $this->valid);
154:     }

but this has the disadvantage that it is not possible to change the value of a control before the validation so a new event (something like “validationSucceeded”) seems to be a better option.

Thank you for a comment.

Last edited by MartyIX (2012-10-28 20:29)

redhead
Member | 1313
+
0
-

And can't you just use the onSuccess callback?

MartyIX
Member | 217
+
0
-

No, there are scenarios when I need: $form->addError() and I cannot do that in onSuccess callback.

Last edited by MartyIX (2012-10-28 20:26)

Jan Tvrdík
Nette guru | 2595
+
0
-

MartyIX wrote:

No, there are scenarios when I need: $form->addError() and I cannot do that in onSuccess callback.

Why? I do it all the time.

MartyIX
Member | 217
+
0
-

Aha. Well, the method fireEvents shows that if you call $form->addError in onSuccess callback then the onError callback is not called. I haven't studied the source code to a greater depth so I may be wrong.

Filip Procházka
Moderator | 4668
+
0
-

I've completely missed this :-/ Would have sended the pullrequest earlier.