Más con Symfony

6.12. Aplicando estilos diferentes para los elementos con errores

Como práctica final, se muestra una utilidad muy sencilla relacionada con el estilo de los elementos de formulario. Imagina que el diseño de la página Product incluye estilos diferentes para los campos que tienen algún error de validación.

Formulario de producto con errores

Figura 6.6 Formulario de producto con errores

Se supone que el diseñador ya ha creado la hoja de estilos que aplica estilos diferentes a los campos de tipo <input> que se encuentren dentro de cualquier elemento <div> con la clase form_error_row. ¿Cómo se pueden añadir fácilmente clases form_row_error en los campos que tengan errores?

Para conseguirlo hay que hacer uso de un objeto especial llamado formateador del esquema de formulario ("form schema formatter"). Todos los formularios de Symfony utilizan este formateador para determinar el código HTML que se debe utilizar cuando se muestran los elementos de formulario. Por defecto Symfony emplea un formateador que hace uso de tablas HTML.

En primer lugar se crea una nueva clase de tipo formateador de formulario que emplea una código HTML más simple al mostrar el formulario. Crea un nuevo archivo llamado sfWidgetFormSchemaFormatterAc2009.class.php y guárdalo en el directorio lib/widget/ (debes crear este directorio a mano):

class sfWidgetFormSchemaFormatterAc2009 extends sfWidgetFormSchemaFormatter
{
  protected
    $rowFormat       = "<div class=\"form_row\">
                        %label% \n %error% <br/> %field%
                        %help% %hidden_fields%\n</div>\n",
    $errorRowFormat  = "<div>%errors%</div>",
    $helpFormat      = '<div class="form_help">%help%</div>',
    $decoratorFormat = "<div>\n  %content%</div>";
}

Aunque el formato de esta clase es un poco raro, la idea básica es que el método renderRow() utiliza el código de $rowFormat para mostrar su información. Las clases de tipo formateador tienen muchas otras opciones que se pueden consultar en la API de symfony 1.3.

Para hacer uso del nuevo formateador en todos los formularios del proyecto, se puede añadir lo siguiente en la clase ProjectConfiguration:

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...

    sfWidgetFormSchema::setDefaultFormFormatterName('ac2009');
  }
}

El objetivo consiste en añadir una clase form_row_error dentro del elemento form_row solamente si ese campo tiene algún error de validación. Añade una variable %row_class% en la propiedad $rowFormat y redefine el método sfWidgetFormSchemaFormatter::formatRow() de la siguiente manera:

class sfWidgetFormSchemaFormatterAc2009 extends sfWidgetFormSchemaFormatter
{
  protected
    $rowFormat       = "<div class=\"form_row%row_class%\">
                        %label% \n %error% <br/> %field%
                        %help% %hidden_fields%\n</div>\n",
    // ...

  public function formatRow($label, $field, $errors = array(), $help = '', $hiddenFields = null)
  {
    $row = parent::formatRow(
      $label,
      $field,
      $errors,
      $help,
      $hiddenFields
    );

    return strtr($row, array(
      '%row_class%' => (count($errors) > 0) ? ' form_row_error' : '',
    ));
  }
}

Con este último cambio, cada elemento que se muestre con el método renderRow() será encerrado por un elemento <div> con la clase form_row_error si ese elemento tiene algún error de validación.