Symfony 1.4, la guía definitiva

10.2. Modificando el aspecto de los formularios

Mostrar un formulario simplemente con echo $form está bien para la fase de prototipado, pero en la aplicación real querrás tener un control preciso del código HTML resultante. El objeto del formulario contiene un array con todos sus campos, y la llamada a echo $form simplemente recorre ese array para mostrarlos uno a uno. Si quieres un control más preciso, puedes iterar sobre los campos del formulario a mano y después ejecutar el método renderRow() sobre cada uno de ellos. El siguiente código produce exactamente el mismo resultado que antes, pero la plantilla muestra cada campo individualmente.

// en modules/mimodulo/templates/contactoSuccess.php
<?php echo $form->renderFormTag('mimodulo/contacto') ?>
  <table>
    <?php echo $form['nombre']->renderRow() ?>
    <?php echo $form['email']->renderRow() ?>
    <?php echo $form['asunto']->renderRow() ?>
    <?php echo $form['mensaje']->renderRow() ?>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

Mostrar cada campo de forma individual no sólo te permite modificar su posición, sino que también puedes controlar su aspecto. Si se pasa un argumento al método renderRow(), se interpreta como la lista de atributos HTML del campo, por lo que puedes añadir por ejemplo los atributos class e id o incluso un evento de JavaScript. El segundo parámetro de renderRow() se emplea para establecer el título o etiqueta del campo, reescribiendo el que Symfony deduce a partir del nombre del widget. A continuación se muestra un ejemplo de formulario de contacto personalizado:

// en modules/mimodulo/templates/contactoSuccess.php
<?php echo $form->renderFormTag('mimodulo/contacto') ?>
  <table>
    <?php echo $form['nombre']->renderRow(array('size' => 25, 'class' => 'miclase'), 'Escribe tu nombre') ?>
    <?php echo $form['email']->renderRow(array('onclick' => 'this.value = "";'), 'Escribe tu email') ?>
    <?php echo $form['mensaje']->renderRow() ?>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

El siguiente paso al personalizar el formulario puede ser el uso de etiquetas <li> en vez de <tr> para mostrar cada campo. En realidad, un campo de formulario está compuesto por su título, opcionalmente un mensaje de error (explicado más adelante en este capítulo), un mensaje de ayuda y un widget para introducir datos (los widgets complejos pueden estar formados por varias etiquetas HTML). De la misma forma que puedes mostrar los campos de un formulario de uno en uno, también puedes mostrar individualmente cada parte de cada campo. Para ello, olvida el método renderRow() y utiliza los métodos render() (para el widget), renderError(), renderLabel() y renderHelp(). Si por ejemplo quieres mostrar todo el formulario con etiquetas <li>, puedes modificar la plantilla por lo siguiente:

// en modules/foo/templates/contactSuccess.php
<?php echo $form->renderFormTag('mimodulo/contacto') ?>
  <ul>
    <?php foreach ($form as $campo): ?>
    <li>
      <?php echo $campo->renderLabel() ?>
      <?php echo $campo->render() ?>
    </li>
    <?php endforeach; ?>
    <li>
      <input type="submit" />
    </li>
  </ul>
</form>

El listado anterior genera el siguiente código HTML:

<form action="/frontend_dev.php/mimodulo/contacto" method="POST">
  <ul>
    <li>
      <label for="nombre">Nombre</label>
      <input type="text" name="nombre" id="nombre" />
    </li>
    <li>
      <label for="email">Email</label>
      <input type="text" name="email" id="email" />
    </li>
    <li>
      <label for="asunto">Asunto</label>
      <select name="asunto" id="asunto">
        <option value="0">Asunto A</option>
        <option value="1">Asunto B</option>
        <option value="2">Asunto C</option>
      </select>
    </li>
    <li>
      <label for="mensaje">Mensaje</label>
      <textarea rows="4" cols="30" name="mensaje" id="mensaje"></textarea>
    </li>
    <li>
      <input type="submit" />
    </li>
  </ul>
</form>

Nota Cada fila de un campo está compuesta por la representación visual que un formateador hace de todos sus elementos (título, mensaje de error, mensaje de ayuda y etiqueta para introducir datos). Symfony utiliza por defecto el formateador table y por eso el método renderRow() genera etiquetas <tr>, <th> y <td>. Para obtener el mismo código HTML que en el último ejemplo, puedes hacer uso de otro de los formateadores que incluye Symfony y que se llama list:

// en modules/mimodulo/templates/contactoSuccess.php
<?php echo $form->renderFormTag('mimodulo/contacto') ?>
  <ul>
    <?php echo $form->renderUsing('list') ?>
    <li>
      <input type="submit" />
    </li>
  </ul>
</form>

Nota Si quieres crear tu propio formateador, consulta la documentación de la API de la clase sfWidgetFormSchemaFormatter.