My favorite Zend_Form decorators configuration
In the previous post I talked about extending Zend_Form. At the end of the post I shortly mentioned decorators and what they do.
The default markup they produce is a definition list. But many web designers (incuding me) prefer some other markup. My favorite XHTML for forms is presented in the Prettier Accessible Forms article at A List Apart. It uses an ordered list instead of a definition list. Here is how to achieve it with Zend_Form decorators (the form is the same as in the last post):
-
class Contact extends Zend_Form
-
{
-
private $elementDecorators = array(
-
'ViewHelper',
-
array(array('data' => 'HtmlTag'), array('tag' => 'div', 'class' => 'element')),
-
'Label',
-
array(array('row' => 'HtmlTag'), array('tag' => 'li')),
-
);
-
-
private $buttonDecorators = array(
-
'ViewHelper',
-
array(array('data' => 'HtmlTag'), array('tag' => 'div', 'class' => 'button')),
-
array(array('row' => 'HtmlTag'), array('tag' => 'li')),
-
);
-
-
private $captchaDecorators = array(
-
'Label',
-
array(array('row' => 'HtmlTag'), array('tag' => 'li'))
-
);
-
-
public function init()
-
{
-
$this->setMethod('post');
-
-
$name = new Zend_Form_Element_Text('name', array(
-
'decorators' => $this->elementDecorators,
-
'label' => 'Your name',
-
'required' => true,
-
'filters' => array(
-
'StringTrim'
-
),
-
'validators' => array(
-
array('StringLength', false, array(3, 50))
-
),
-
'class' => 'input-text'
-
));
-
-
$email = new Zend_Form_Element_Text('email', array(
-
'decorators' => $this->elementDecorators,
-
'label' => 'Your email',
-
'required' => true,
-
'filters' => array(
-
'StringTrim'
-
),
-
'validators' => array(
-
'EmailAddress'
-
),
-
'class' => 'input-text'
-
));
-
-
$subject = new Zend_Form_Element_Text('subject', array(
-
'decorators' => $this->elementDecorators,
-
'label' => 'Subject',
-
'required' => true,
-
'filters' => array(
-
'StringTrim'
-
),
-
'validators' => array(
-
array('StringLength', false, array(3, 50))
-
),
-
'class' => 'input-text'
-
));
-
-
$message = new Zend_Form_Element_Textarea('message', array(
-
'decorators' => $this->elementDecorators,
-
'label' => 'Message',
-
'rows' => 10,
-
'cols' => 50,
-
'required' => true,
-
'filters' => array(
-
'StringTrim'
-
),
-
'validators' => array(
-
array('StringLength', false, array(20, 1500))
-
)
-
));
-
-
$captcha = new Zend_Form_Element_Captcha('captcha', array(
-
'decorators' => $this->captchaDecorators,
-
'label' => 'Are you a human?',
-
'helper' => null,
-
'captcha' => array(
-
'captcha' => 'Figlet',
-
'wordLen' => 6,
-
),
-
'class' => 'input-text'
-
));
-
-
$submit = new Zend_Form_Element_Submit('contact', array(
-
'decorators' => $this->buttonDecorators,
-
'label' => 'Submit',
-
'class' => 'input-submit'
-
));
-
-
$this->addElements(array($name, $email, $subject, $message, $captcha, $submit));
-
}
-
-
public function loadDefaultDecorators()
-
{
-
$this->setDecorators(array(
-
'FormErrors',
-
'FormElements',
-
array('HtmlTag', array('tag' => 'ol')),
-
'Form'
-
));
-
}
-
}
Standard decorators for form elements are:
- ViewHelper (the element tag, for example <input> or <textarea>)
- Errors (errors, by default in <ul>)
- HtmlTag (<dd> by default)
- Label (wrapped in <dt> by default)
Standard decorators for the form are:
- FormElements (iterates through form elements)
- HtmlTag (<dl> by default)
- Form (<form>)
I use another decorator to display form errors all on top of the form:
- FormErrors
In the form class above I have defined customized decorators for some form elements. In case there were checkboxes or radio buttons in the form, I would add these decorators:
-
private $checkboxDecorators = array(
-
'Label',
-
'ViewHelper',
-
array(array('data' => 'HtmlTag'), array('tag' => 'div', 'class' => 'checkbox')),
-
array(array('row' => 'HtmlTag'), array('tag' => 'li')),
-
);
-
-
private $radioDecorators = array(
-
'Label',
-
'ViewHelper',
-
array(array('data' => 'HtmlTag'), array('tag' => 'div', 'class' => 'radio')),
-
array(array('row' => 'HtmlTag'), array('tag' => 'li')),
-
);
The loadDefaultDecorators() method applies custom decorators to the form object. The decorators are rendered from inside in the order they are specified. So it works like this:
- FormErrors is rendered.
- FormElements is rendered.
- The <ol> tag is rendered.
- Finally, the <form> tag is rendered (wrapping all other content inside it).
In conclusion, every decorator renders only its own content and the final form consists of all decorators clumped together.

Hi. I like the way you write. Will you post some more articles?
Sure I will write new posts in the future. I’m in the middle of something (larger project) right now though so I don’t have much time.
You don’t want to set decorators on EACH element of EACH your form, it is much better to extend Zend_Form as My_Form and set your decorators there ONCE and forget about the annoying dl dt dd tags forever
Hi Richard,
Nice to see others also have a handy way to change the markup for those standard elements. Have you found a way to change the markup for the Errors element. I want to but can’t seem to find it without having to do so through the elements view->getHelper(‘formErrors’)
I also came up with something similar with which you don’t need to add the decorators in your definition at all. But should you wish to you still can.
I also have some example code up for download. Check my post about this subject at http://www.sreknord.net/blog/zend-framework/configure-zend-framework-standard-form-decorators