views:

52

answers:

2

Hi all,

I'm trying to create a form that change the validation of a field based on the select option from the html form field.

Ex: if user select a option 1 from drop down field "options", I want the field "metric" to validate as sfValidatorInteger. If user select option 2 from field "options", I want the field "metric" to validate as sfValidatorEmail, etc.

So inside the public function configure() { I have the switch statement to capture the value of "options", and create the validator based on that value returned from the "options".

1.) How do I capture the value of "options" ? I've tried:

$this->getObject()->options
$this->getTaintedValues()

The only thing that's currently working for me is but it's not really MVC:

$params = sfcontext::getInstance()->getRequest()->getParameter('options');

2.) Once I've captured that information, how can I assign the value of "metric" to a different field? ("metric" is not a real column in db). So I need to assign the value of "metric" to different field such as "email", "age" ... Currently I'm handling this at the post validator like this, just wondering if I can assign value within the configure():

$this->validatorSchema->setPostValidator(new sfValidatorCallback(array('callback' => array($this, 'checkMetric'))));

public function checkMetric($validator, $values) {

}

Thanks!

A: 

Hello

1) In a post validator, values can be accessed by using the $values parameter. Just use $values['options'] and it should be fine... or did you want to access this values from another part of you code? $this->getObject()->widgetSchema['options'] should work too I think, once your form is bound to an object.

2) The configure() method is called at the end of the form constructor, so values are not bound nor accessible yet, unless you are initializing your form with an object from the db (which does not require any validation). But if you want to initialize your form from $_POST, a post validator is definitely the way to go IMHO.

greg0ire
thank you for your answer. It's really helpful and I decided to move my code to the post validator and capturing the $values as you suggested. Thanks.
KienPham.com
+2  A: 

You want to use a post validator. Try doing something like this in your form:

public function configure()
{
  $choices = array('email', 'integer');
  $this->setWidget('option', new sfWidgetFormChoice(array('choices' => $choices))); //option determines how field "dynamic_validation" is validated
  $this->setValidator('option', new sfValidatorChoice(array('choices' => array_keys($choices)));
  $this->setValidator('dynamic_validation', new sfValidatorPass()); //we're doing validation in the post validator
  $this->mergePostValidator(new sfValidatorCallback(array(
    'callback' => array($this, 'postValidatorCallback')
  )));
}

public function postValidatorCallback($validator, $values, $arguments)
{
   if ($values['option'] == 'email')
   {
     $validator = new sfValidatorEmail();
   }
   else //we know it's one of email or integer at this point because it was already validated
   {
     $validator = new sfValidatorInteger();
   }
   $values['dynamic_validation'] = $validator->clean($values['dynamic_validation']); //clean will throw exception if not valid
   return $values;
}
jeremy
Thank you for your help! I got it to work this way. I didn't know about mergePostValidator and $validator->clean().Do you know of a way to attach the field name to the error message that are being thrown by $validator->clean() ?. In this case it would be the 'option' field.
KienPham.com