Combining input and choice widget in symfony

This article has moved to this location.

A few month ago, i was redevelop an application, using an existing database. One of the problems I encountered, there is a field whose content is a mixture of integer and string. For example: “1 Day”, “3 Month”, “5 Year”. where the string input should one of the three above (Day or Month or Year).

To overcome this problem, I created a custom widget, which is a combination of input and choice widget. Below is the custom widget i created :

class myWidgetFormInputTextAndChoice extends sfWidgetForm
  protected function configure($options = array(), $attributes = array())
	$this->addOption('text', array());
	$this->addOption('choice', array());
	$this->addOption('format', '%text% %choice%');
	parent::configure($options, $attributes);

  public function render($name, $value = null, $attributes = array(), $errors = array())
       if (null !== $value)
           if (false === is_array($value))
                $tmp = explode(' ', $value);
                $value = array();
                $value['text'] = $tmp[0];
                $value['choice'] = $tmp[1];
       $text = $this->getTextWidget($attributes)->render($name.'[text]', $value['text']);
       return strtr($this->getOption('format'), array(
          '%text%' => $text,
          '%choice%' => $this->getChoiceWidget($attributes)->render($name.'[choice]', $value['choice']),

  protected function getTextWidget($attributes = array())
    return new sfWidgetFormInputText($this->getOptionsFor('text'), $this->getAttributesFor('text', $attributes));

  protected function getChoiceWidget($attributes = array())
    return new sfWidgetFormChoice($this->getOptionsFor('choice'), $this->getAttributesFor('choice', $attributes));

  protected function getOptionsFor($type)
    $options = $this->getOption($type);
    if (!is_array($options))
      throw new InvalidArgumentException(sprintf('You must pass an array for the %s option.', $type));
    return $options;

  protected function getAttributesFor($type, $attributes)
    $defaults = isset($this->attributes[$type]) ? $this->attributes[$type] : array();
    return isset($attributes[$type]) ? array_merge($defaults, $attributes[$type]) : $defaults;


And here is the validator

class myValidatorInputTextAndChoice extends sfValidatorBase
   public function configure($options = array(), $messages = array())
 	parent::configure($options, $messages);
	$this->addOption('text_field', 'text');
	$this->addOption('choice_field', 'choice');

  public function doClean($value)
       $textField = $this->getOption('text_field');
       $choiceField = $this->getOption('choice_field');
       $value[$textField] = $this->getOption('text')->clean(isset($value[$textField]) ? $value[$textField] : null);
       $value[$choiceField]   =  $this->getOption('choice')->clean(isset($value[$choiceField]) ? $value[$choiceField] : null);

       if ($value[$textField] && $value[$choiceField])
    	    return $value[$textField].' '.$value[$choiceField];
       return $value;

To use the widget, in the form configure() :

$choices = array('Day'=>'Day', 'Month'=>'Month', 'Year'=>'Year');
$this->widgetSchema['your_widget'] = new myWidgetFormInputTextAndChoice(array('choice'=>array('choices'=>$choices)));
$this->validatorSchema['your_widget'] = new myValidatorInputTextAndChoice(array('text'=>new sfValidatorInteger(), 'choice'=>new sfValidatorChoice(array('choices'=>array_keys($choices)))));

$this->setDefault('your_widget', '1 Year');

One response to “Combining input and choice widget in symfony

  1. Prasad December 13, 2011 at 11:40 am

    Thanks so much. Very soon I will write a phone-number widget to display country code, area code & number.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: