Zend Form Decorator, parte I

Los formularios de Zend Framework es una de las cosas que más me gustan del framework porque te permite validar, procesar y modificar los formularios de una forma muy rápida y limpia. No obstante, de entrada queda todo muy limitado por la forma de presentar los datos con una lista de definición (dl). Aveces soy muy purista, y usar dl, dt y dd para maquetar un formulario no lo encuentro nada semántico (y tampoco con li).

La primera necesidad que me surge es cambiar el dl por un div y los dt’s y dd’s por p’s del formulario:

$form->clearDecorators()
	->addDecorator('FormElements')
	->addDecorator('HtmlTag', 	array('tag' => '', 'class' => 'zend_form'))
	->addDecorator('Form')
	->setElementDecorators(array(
		array('ViewHelper'),
		array('Errors'),
		array('Description', 	array('tag' => 'span', 'class' => 'element-description')),
		array('Label', 			array('separator' => ' ')),
		array('HtmlTag', 		array('tag' => 'p', 'class' => 'element-group')
	),
));

De esta forma todos los elementos del formulario estarán construidos con una p y con la clase element-group, las ayudas descriptivas estaran dentro de la misma p pero dentro de un span y con la clase element-group-description

El segundo aspecto es hacer que el submit no tenga label, para eso basta con no ponerlo, pero al hacerlo con listas de definición nos crea un dt vacío. pero además quiero que disponga de un link de “volver” o “cancelar”:

$form->addElement('submit', 'submit', array(
	'ignore'   		=> true,
	'description'	=> '<a href=\"#\">Cancel</a>',
	'decorators' 	=> array(
		array('ViewHelper'),
		array('Description', 	array('escape' => false, 'tag' => 'span', 'class'=>'element-canel-link')),
		array('HtmlTag', 		array('tag' => 'p', 'class'=>'submit-group'))
	)
));

Aquí lo importante son los valores que pasamos a la array Description y lo mismo lo podemos hacer para un input.

$form->addElement('password', 'credential', array(
	'label'      	=> 'Password',
	'required'   	=> true,
	'filters'    => array('StringTrim', 'StripTags'),
	'description'	=> '<a href=\"#\">Remember password</a>',
	'decorators' 	=> array(
		array('ViewHelper'),
		array('Description', 	array('escape' => false, 'tag' => 'span', 'class'=>'element-description')),
		array('Label', 			array('separator'=>' ')),
		array('Errors'),
		array('HtmlTag', 		array('tag' => 'p', 'class'=>'element-group'))
	)
));

Otro gran problema que se presenta con Zend Form es que al imprimir un checkbox lo pone después del label y eso es poco usable.

$form->addElement('checkbox', 'rememberme', array(
	'label'     => 'Remember me',
	'value'		=> '1',
	'checked' 	=> false,
	'decorators' 	=> array(
		array('ViewHelper'),
		array('Label', 			array('placement' => 'APPEND')),
		array('Errors'),
		array('HtmlTag', 		array('tag' => 'p', 'class'=>'element-group'))
	)
));

(Creo que aquí hay un bug, además del checbox me ha añadido un input hidden, pero no debería darnos muchos problemas, espero))

De esta forma my clase formulario queda así:

class Default_Form_Login extends Zend_Form
{
    /**
     * init()
     *
     * @see    http://framework.zend.com/manual/en/zend.form.html
     * @return void
     */
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');
        $this->setAction('/auth/login/');
        $this->setAttrib('id', 'loginForm');

        $this->clearDecorators()
        	->addDecorator('FormElements')
         	->addDecorator('HtmlTag', array('tag' => '

', 'class' => 'zend_form')) ->addDecorator('Form') ->setElementDecorators(array( array('ViewHelper'), array('Errors'), array('Description', array('tag' => 'span', 'class' => 'element-description')), array('Label', array('separator' => ' ')), array('HtmlTag', array('tag' => 'p', 'class' => 'element-group') ), )); $this->addElement('text', 'identity', array( 'label' => 'Email', 'value' => '', 'required' => true, 'filters' => array('StringTrim', 'StripTags', 'StringToLower'), 'validators' => array('EmailAddress'), )); $this->addElement('password', 'credential', array( 'label' => 'Password', 'required' => true, 'filters' => array('StringTrim', 'StripTags'), 'description' => '<a href=\"#\">Remember password</a>', 'decorators' => array( array('ViewHelper'), array('Description', array('escape' => false, 'tag' => 'span', 'class'=>'element-description')), array('Label', array('separator'=>' ')), array('Errors'), array('HtmlTag', array('tag' => 'p', 'class'=>'element-group')) ) )); $this->addElement('checkbox', 'rememberme', array( 'label' => 'Remember me', 'value' => '1', 'checked' => false, 'decorators' => array( array('ViewHelper'), array('Label', array('placement' => 'APPEND')), array('Errors'), array('HtmlTag', array('tag' => 'p', 'class'=>'element-group')) ) )); // Add the submit button $this->addElement('submit', 'submit', array( 'ignore' => true, 'description' => '<a href=\"#\">Cancel</a>', //set decorator 'decorators' => array( array('ViewHelper'), array('Description', array('escape' => false, 'tag' => 'span', 'class'=>'element-canel-link')), array('HtmlTag', array('tag' => 'p', 'class'=>'submit-group')) ) )); // And finally add some CSRF protection $this->addElement('hash', 'csrf', array( 'ignore' => true, //set decorator 'decorators' => array( array('ViewHelper'), array('HtmlTag', array('tag' => 'p', 'class'=>'element-group-hidden')) ) )); } }

Lo ideal sería crear una clase con Zend_Form_Decorator para que realizará estos cambios automáticamente, pero eso es ya lo dejo para otro post. Así que hasta aquí la primera parte de los Decorators, otro día (espero) veremos como tratar otros elementos, los errores, etc…



1

Comentario

  1. marco dijó el 22 Marzo de 2010 a las 19:20

    Excelente articulo amigo:

    me ayudo mucho, gracaias


Deja tu comentario

Trackback URI | RSS de Comentarios

Un poco de html es bueno: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>