devexp DEVelopment EXPerience, shared with the world!

23Apr/099

sfWidgetFormInputCheckbox unchecked bug

Ever tried to create a Symfony form with a check box input field, which by default should be unchecked ? No ? Well read on because it's not that easy :) .

This would be the code to print a check box input field in a Symfony form:

class CheckboxForm extends BaseCheckboxForm {
 public function configure() {
 $this->widgetSchema['field'] = new sfWidgetFormInputCheckbox();
 }
}

When you use the form to create something then by default the check box should be unchecked. And when you use this form for editing, then the check box should be checked if the object you try to edit has already been checked in the past.

If you try this code, you'll see that the check box will always be checked. Even if you display this form to create a new object. Strange no ?

The problem is due to a bug in the Symfony sfWidgetFormInputCheckbox class. Even worse, this bug has been reported the first time 10 months ago (trac #3917) and 1 month later (trac #3996) and it's still not fixed ! (grrrrr)

Until Symfony bug fixes this issue, there are 2 work a rounds you can use.

1. Edit the sfWidgetFormInputCheckbox class and patch it:

actual

class sfWidgetFormInputCheckbox extends sfWidgetFormInput
{
 ...
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false)
 {
 $attributes['checked'] = 'checked';
 }
 ...
 }
}

patched

class sfWidgetFormInputCheckbox extends sfWidgetFormInput
{
 ...
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false && $value != 0)
 {
 $attributes['checked'] = 'checked';
 }
 ...
 }
}

I would not recommend this, because if like us, you have more than one Symfony environment, there is a chance that you could forget to patch it. And worse if Symfony releases a new version without the bug fix you'll have to remember to re patch the file.

2. Extend the sfWidgetFormInputCheckbox class and override the render method:

Edit: Put this class in the lib folder and call it myOwnWidgetFormInputCheckbox.class.php. After that run symfony cc.

/**
 * FIXME: This class can be removed if the sfWidgetFormInputCheckbox bug
 * has been resolved in symfony.
 */
class myOwnWidgetFormInputCheckbox extends sfWidgetFormInputCheckbox
{
 /**
 * Override render method due to symfony bug (http://trac.symfony-project.org/ticket/3917)
 */
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false && $value != 0)
 {
 $attributes['checked'] = 'checked';
 } 

 if (!isset($attributes['value']) && !is_null($this->getOption('value_attribute_value'))) {
 $attributes['value'] = $this->getOption('value_attribute_value');
 }

 return parent::render($name, null, $attributes, $errors);
 }
}

Your form class should then be changed to:

class CheckboxForm extends BaseCheckboxForm {
 public function configure() {
 $this->widgetSchema['field'] = new myOwnWidgetFormInputCheckbox();
 }
}

This was very easy to solve, but we lost a lot of time in finding the reason why this stupido check box was always checked. And why the hell is this bug still not solved in Symfony ?

In the mean time patch your symfony or create your own checkbox widget :) .

Bookmark and Share
Comments (9) Trackbacks (0)
  1. I agree – why isn’t this fixed yet? something so basic as a checkbox accurately displaying what it should do…. anyway :-) thanks for the info :-)

  2. Great patch – thank you.
    BTW – Have you ever thought about fixing the bug yourself instead of insulting the symfony guys? They gave us their time to create this great piece of software that saves us all a lot of time?

    Stevie

  3. Stevie: I did fix it myself … searched for it for hours and finally post it here.

    And there’s a big difference between wondering why a bug is still not fixed, and insulting the symfony guys !!!

  4. to Stevie > thx for commenting on our blog, we do appreciate a nice comment and hope to get more interaction with our readers.

    But unfortunately if you will get into this issue a bit more, and really try to understand the problem, you’ll see that this bug hasn”t been fixed in Symfony.

    As you can see on the right side of our blog, we adore Symfony and do anything to get it to the attention of our visitors as this is like you say a great piece of software.
    But like in all soft wares, it might contain some bugs, and those need to be fixed. By taking action and putting this bugfix on our blog, it might get the attention of Fabien Potencier and his crew, and in the next version get a fix.

    Isn’t a community the most important for the open source software developers? i guess so.
    So to conclude your comment: thx for your comment, but think before you write ;-)

  5. It may not be obvious to people who are still relatively new to Symfony, but the above file (which works perfectly!) should be placed in a file named ‘myOwnWidgetFormInputCheckbox.class.php’ in the base /lib directory of the project, and clear the cache.

    The name of the class and the name of the file have to stay in sync (I renamed mine to refer to trac3917).

    Thanks a lot for this tip, it was a great help

  6. Just ran into this problem and found your article. Very timely and helpful – thanks!

  7. Thanks for the tip what to do with ‘checked’ issue.

    Just wanted to add my 5 cents:
    Condition with only $value in patched widget looks simpler/cleaner then 3 part conjunction.

    if ($value) instead line 06. (`patched` listing in first solution).

  8. Great solution, just what I was looking for!
    Created my own validator and was bugged by the fact that the cleaned value would not appear.
    Thanks.

  9. Hi

    why not just change your DB schema ? symfony works well if the value is null
    So if you change your schema and reload your data (and maybe make some update) everything work
    I understood that because of your patch


Leave a comment



No trackbacks yet.