25-03-2009 Luis Artola
Zend_Form es uno de los componentes estrella del Zend Framework. Muchas son las ventajas de utilizarlo (generación de apariencia, validación de html, limpieza del código, etc.). El problema es que a menudo podemos encontrarnos con el problema de que la apariencia que genera el propio Zend_Form no nos interesa. Es cierto que podemos personalizarla mediante los decorators. Pero incluso estos pueden resultarnos limitados.
En el ejemplo que expongo a continuación, queremos generar una tabla de checkbox para puntuar del 1 al 3 (malo, regular, bueno) una serie de conceptos. Como veréis, la manera de hacerlo es sobreescribiendo el método render, aunque necesitaremos un poco más de código para hacerlo funcionar todo.
Por supuesto, éste ejemplo podría complicarse infinitamente, si se quisiera mezclar el render por defecto, con un render personalizado. Y, cuidado, ésta técnica es algo sucia y sólo debería utilizarse cuando la posibilidad de crear nuestros propios Zend_Form_Elements o Zend_Form_Decorators es demasiado costosa o insuficiente.
<?php class MyForm extends Zend_Form{ protected $valores = array(); function __construct(){ /* Aquí se declararían los elementos del zend form que se van a utilizar, sus tipos, valores, validaciones, etc... Éste Zend Form se va a utilizar como cualquier otro formulario. Aprovecharemos la posibilidad de validarlo desde en controller, etc.. Lo único que cambia es que cuando invoquemos render() no se generará de manera regular, sino de la manera que a nosotros nos plazca. */ }//construct //sobreescribimos el método setDefaults, que Zend_Form llama cuando se van a introducir valores por defecto en el formulario. // setDefaults también es llamado desde el método populate del Zend_Form. public function setDefaults(array $values){ // guardamos en "valores" la lista de valores de los campos //del formulario, para luego poder utilizarlos en el método render() $this->valores = $values; parent::setDefaults(); }//setDefaults function render(Zend_View_Interface $view = null){ return "<table> <thead> <tr> <th></th> <th>Malo</th> <th>Regular</th> <th>Bueno</th> </tr> </head> <tbody> <tr> <td>Concepto 1 </td> <td> <input ".(($this->valores['concepto1'] == 1)?'checked':'')." type="radio" name = "concepto1" value = "1"/> </td> <td> <input ".(($this->valores['concepto1'] == 1)?'checked':'')." type="radio" name = "concepto1" value = "2"/> </td> <td> <input ".(($this->valores['concepto1'] == 1)?'checked':'')." type="radio" name = "concepto1" value = "3"/> </td> </tr> <tr> <td>Concepto 2 </td> <td> <input ".(($this->valores['concepto2'] == 1)?'checked':'')." type="radio" name = "concepto2" value = "1"/> </td> <td> <input ".(($this->valores['concepto2'] == 1)?'checked':'')." type="radio" name = "concepto2" value = "2"/> </td> <td> <input ".(($this->valores['concepto2'] == 1)?'checked':'')." type="radio" name = "concepto2" value = "3"/> </td> </tr> <tr> <td>Concepto 3 </td> <td> <input ".(($this->valores['concepto3'] == 1)?'checked':'')." type="radio" name = "concepto3" value = "1"/> </td> <td> <input ".(($this->valores['concepto3'] == 1)?'checked':'')." type="radio" name = "concepto3" value = "2"/> </td> <td> <input ".(($this->valores['concepto3'] == 1)?'checked':'')." type="radio" name = "concepto3" value = "3"/> </td> </tr> </tbody> </table> "; }//render } // MyForm ?>
1. Pablo Morales | marzo 25th, 2009 at 8:46 pm
Mucho html embebido.
En realidad lo ideal es crear un grupo, y un grupo por cada fila que esta entre tr y cada elemento encerrarlo dentro de td.
Si necesitas mas Personalizacion (todavia no hay formulario que no pueda hacer sin evitar el uso de html, pero podes usar esto
http://codeutopia.net/blog/2008/10/23/complex-custom-elements-in-zend_form/
2. Luis Artola | marzo 26th, 2009 at 11:40 am
hola pablo,
lo que pasa es que me parece que el Zend_Form tiende bastante a la sobreingeniería (overengineering). A veces resulta demasiada orientación a objetos para cosas muy simples….
comentas que “lo ideal” es crear un grupo y un grupo por cada fila… pero para mí eso no es “ideal”… en todo caso será “lo correcto”…
Un saludo!
3. David | abril 3rd, 2009 at 2:32 pm
¿ Al hacer esto no se pierde algunas funcionalidades como la validación ?
Salu2
4. Luis Artola | abril 3rd, 2009 at 4:34 pm
Hola David,
ojo que en el __construct se declaran los elementos normalmente y su validación también… lo que pasa es que no he escrito el código en el ejemplo….
un saludo!
5. Francisco | febrero 21st, 2010 at 8:22 pm
aghhhhh, un metodo que retorna html embebido!
sacrilegio…