phpsymfony1symfony-forms

Outputting required field indicator for symfony forms


I have a few forms configured in symfony. One things I need is to have an asterisk (*) or other indicator next to fields that are required. The fields are all set to required int he form framework, and return a "this field is required" error when the form is submitted, but I want an indicator before the form is submitted.

If there any way to do this without overriding the labels for each field manually?


Solution

  • Here's an automatic solution found in Kris Wallsmith's blog:

    lib/formatter/RequiredLabelsFormatterTable.class.php, this will add a 'required' class to the labels of required fields

    <?php
    
    class RequiredLabelsFormatterTable extends sfWidgetFormSchemaFormatterTable
    {
      protected
        $requiredLabelClass = 'required';
    
      public function generateLabel($name, $attributes = array())
      {
        // loop up to find the "required_fields" option
        $widget = $this->widgetSchema;
        do {
          $requiredFields = (array) $widget->getOption('required_fields');
        } while ($widget = $widget->getParent());
    
        // add a class (non-destructively) if the field is required
        if (in_array($this->widgetSchema->generateName($name), $requiredFields)) {
          $attributes['class'] = isset($attributes['class']) ?
            $attributes['class'].' '.$this->requiredLabelClass :
            $this->requiredLabelClass;
        }
    
        return parent::generateLabel($name, $attributes);
      }
    }
    

    lib/form/BaseForm.class.php, this is the common base class for all the forms in your project:

      protected function getRequiredFields(sfValidatorSchema $validatorSchema = null, $format = null)
      {
        if (is_null($validatorSchema)) {
          $validatorSchema = $this->validatorSchema;
        }
    
        if (is_null($format)) {
          $format = $this->widgetSchema->getNameFormat();
        }
    
        $fields = array();
    
        foreach ($validatorSchema->getFields() as $name => $validator) {
          $field = sprintf($format, $name);
          if ($validator instanceof sfValidatorSchema) {
            // recur
            $fields = array_merge(
              $fields,
              $this->getRequiredFields($validator, $field.'[%s]')
            );
          } else if ($validator->getOption('required')) {
            // this field is required
            $fields[] = $field;
          }
        }
    
        return $fields;
      }  
    

    add the following few lines to BaseForm as well, in the __construct() method:

    $this->widgetSchema->addOption("required_fields", $this->getRequiredFields());
    $this->widgetSchema->addFormFormatter('table',
      new RequiredLabelsFormatterTable($this->widgetSchema)
    );   
    

    After all this, all your labels will have the required class, use whatever css you need to mark it to the user.