Home > Symfony Framework > Symfony 1.2 sfForm formatter to add stars on required fields

Symfony 1.2 sfForm formatter to add stars on required fields

August 31st, 2009

The following is a form formatter class I developed to automatically add stars * on required fields. Feel free to use it and let me know if it can be improved.

You might ask, why not just use setLabels?

Firstly, if you already set required fields to true/false in setValidators, why do you have to add the stars manually again in setLabels? It just doesn’t make sense!

Secondly, using setLabels to add stars is interfering with language translation.

Thirdly, this is I believe a proper (or proper-ish?) way to do this kind of things with sfForm.

OK, let’s get into it!

Below is an example on how to use it in your form class

<?php
 
class yourForm extends sfForm
{
  function configure()
  {
    $this->setWidgets(array(
      'first_name'           => new sfWidgetFormInput(array(), array('maxlength' => 50)),
      'last_name'            => new sfWidgetFormInput(array(), array('maxlength' => 50)),
      'email'                => new sfWidgetFormInput(array(), array('maxlength' => 128)),
    ));
 
    $this->setValidators(array(
      'first_name'           => new sfValidatorString(array('max_length' => 50, 'required' => true)),
      'last_name'            => new sfValidatorString(array('max_length' => 50, 'required' => false)),
      'email'                => new sfValidatorEmail(array('max_length' => 128, 'required' => true)),
    ));
 
    $decorator = new sidFormFormatter($this->widgetSchema, $this->validatorSchema);
    $this->widgetSchema->addFormFormatter('custom', $decorator);
    $this->widgetSchema->setFormFormatterName('custom');    
  }
}

This is optional but you might want to add the following into your css (e.g.: main.css)

em.required {font-size:1.2em;font-weight:bold;margin:0px;padding:0px;}
label.required {font-weight:bold;}

Last but most importantly, save this formatter class in your project lib folder as sidFormFormatter.php:

<?php
 
class sidFormFormatter extends sfWidgetFormSchemaFormatter {
 
  protected 
    $rowFormat = "\n%error%\n<div class=\"formRow\">\n<div class=\"formLabel\">%label%</div>\n<div class=\"formField\">%field%\n%help%</div></div>\n%hidden_fields%",
    $helpFormat = '<div class="fieldHelp">%help%</div>', 
    $errorRowFormat = "<div>\n%errors%<br /></div>\n", 
    $errorListFormatInARow = "<ul>%errors%</ul>\n", 
    $errorRowFormatInARow =  "<li class=\"error\">&darr; %error% &darr;</li>\n", 
    $namedErrorRowFormatInARow = "<li class=\"error\">&darr; %error% &darr;</li>\n", 
    $decoratorFormat = "%content%";
 
  /**
   * @var sfValidatorSchema
   */
  protected $validatorSchema = null;
 
  /**
   * @var array
   */
  protected $params = array();
 
  /**
   * Constructor
   *
   * Params:
   *  - "required_label_class_name" css class name for label tag when the field is required field, the default is 'required'.
   *  - "required_label_format" default is '%label% <em class="required">*</em>'.
   *
   * @param sfWidgetFormSchema $widgetSchema
   * @param sfValidatorSchema $validatorSchema
   * @param array $params
   */
  public function __construct(sfWidgetFormSchema $widgetSchema, sfValidatorSchema $validatorSchema, $params = array())
  {
    $this->validatorSchema = $validatorSchema;
    $this->params = $params;
    parent::__construct($widgetSchema);
  }
 
  /**
   * Returns parameter identified with $name or if does not exist, returns $default.
   *
   * @param string $name
   * @param mixed $default
   * @return mixed
   */
  public function getParameter($name, $default=null)
  {
    if (!isset($this->params[$name]))
    {
      return $default;
    }
 
    return $this->params[$name];
  }
 
  /**
   * Generates a label for the given field name.
   *
   * @param  string $name        The field name
   * @param  array  $attributes  Optional html attributes for the label tag
   *
   * @return string The label tag
   */
  public function generateLabel($name, $attributes = array())
  {
    $is_required = false;
    if ( $this->validatorSchema and isset($this->validatorSchema[$name]) )
    {
      $validator = $this->validatorSchema[$name];
      /* @var $validator sfValidatorBase */
 
      if ( $validator->getOption('required') )
      {
        $class_name = $this->getParameter('required_label_class_name', 'required');
        if (isset($attributes['class'])) $attributes['class'] .= ' '.$class_name; else $attributes['class'] = $class_name;
        $is_required = true;
      }
    }
 
    $s = parent::generateLabel($name, $attributes);
 
    if ($is_required)
    {
      $format = $this->getParameter('required_label_format', '%label% <em class="required">*</em>');
      $s = str_replace('%label%', $s, $format);
    }
 
    return $s;
  }
}

That’s it! Don’t forget to “symfony cc” (clear cache).

Happy coding!

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

Symfony Framework , ,

  1. beleneglorion
    August 31st, 2009 at 01:31 | #1

    Nice code, perhaps could you make the “required” class configurable by passing options to the constructor, and do not replace $attributes['class'] by “required” concaten it, make the “*” configurable too

  2. Sid
    August 31st, 2009 at 02:04 | #2

    Hi, thank you for the feedback. I’ve updated the code.

  3. August 31st, 2009 at 04:49 | #3

    Thanks for sharing this. Your getParameter() method can be shorted as below to gain in readability :

    public function getParameter($name, $default=null)
    {
    if (!isset($this->params[$name]))
    {
    return $default;
    }

    return $this->params[$name];
    }

    ++

  4. Sid
    August 31st, 2009 at 10:06 | #4

    Thank you for the feedback, code is updated :)

  5. September 1st, 2009 at 22:32 | #5

    Hi,

    Nice code! I try it, it works but I need update your constructor by updating sfWidgetSchema in sfWidgetFormSchema.

    Hope it helps

  6. Bob Saget
    September 7th, 2009 at 13:34 | #6

    I agree with TIM. I also struggled a bit with the code but after changing the sfWidgetSchema tosfWidgetFormSchema in the Constructor, everything worked perfectly and oh so elegantly ! :)

    Thanks for the code !

  7. Sid
    September 7th, 2009 at 13:44 | #7

    Thanks for the feedback. I have updated the code to use sfWidgetFormSchema instead of sfWidgetSchema.

  8. November 16th, 2009 at 15:14 | #8

    Well done !

  9. Sid
    January 19th, 2010 at 00:06 | #9

    @Antoine

    Thanks :)

  10. Gareth
    February 24th, 2010 at 17:13 | #10

    Just wondering if there was some way in the Form class to just add specific row formatting for 1 or 2 elements as this is unique to just this form, instead of having to create an entire decorator class to handle it.

  1. No trackbacks yet.
Subscribe to comments feed