Zend_Form
ships with several standard decorators. For more
information on general decorator usage, see the Decorators section.
The Callback decorator can execute an arbitrary callback to
render content. Callbacks should be specified via the 'callback'
option passed in the decorator configuration, and can be any
valid PHP callback type. Callbacks should accept three
arguments, $content
(the original content passed to
the decorator), $element
(the item being
decorated), and an array of $options
. As an example
callback:
class Util { public static function label($content, $element, array $options) { return '<span class="label">' . $element->getLabel() . "</span>"; } }
This callback would be specified as array('Util',
'label')
, and would generate some (bad) HTML markup
for the label. The Callback decorator would then either replace,
append, or prepend the original content with the return value of
this.
The Callback decorator allows specifying a NULL
value for the
placement option, which will replace the original content with
the callback return value; 'prepend' and 'append' are still
valid as well.
The Captcha decorator is for use with the CAPTCHA form
element. It utilizes the CAPTCHA adapter's
render()
method to generate the output.
A variant on the Captcha decorator, 'Captcha_Word', is also commonly used, and creates two elements, an id and input. The id indicates the session identifier to compare against, and the input is for the user verification of the CAPTCHA. These are validated as a single element.
The Description decorator can be used to display a description set
on a Zend_Form
, Zend_Form_Element
, or
Zend_Form_DisplayGroup
item; it pulls the description
using the object's getDescription()
method. Common use
cases are for providing UI hints for your elements.
By default, if no description is present, no output is generated. If
the description is present, then it is wrapped in an HTML
p tag by default, though you may specify a tag by
passing a tag option when creating the decorator, or
calling setTag()
. You may additionally specify a class
for the tag using the class option or by calling
setOption('class', 'foo')
; by default, the class 'hint' is used.
The description is escaped using the view object's escaping
mechanisms by default. You can disable this by passing a
FALSE
value to the decorator's 'escape' option or
setEscape()
method.
The default decorators utilize definition lists (<dl>) to render form elements. Since form items can appear in any order, display groups and sub forms can be interspersed with other form items. To keep these particular item types within the definition list, the DtDdWrapper creates a new, empty definition term (<dt>) and wraps its content in a new definition datum (<dd>). The output looks something like this:
<dt></dt> <dd><fieldset id="subform"> <legend>User Information</legend> ... </fieldset></dd>
This decorator replaces the content provided to it by wrapping it within the <dd> element.
Element errors get their own decorator with the Errors decorator. This decorator proxies to the FormErrors view helper, which renders error messages in an unordered list (<ul>) as list items. The <ul> element receives a class of "errors".
The Errors decorator can either prepend or append the content provided to it.
Display groups and sub forms render their content within
fieldsets by default. The Fieldset decorator checks for either a
'legend' option or a getLegend()
method in the
registered element, and uses that as a legend if non-empty. Any
content passed in is wrapped in the HTML fieldset, replacing the
original content. Any attributes set in the decorated item are
passed to the fieldset as HTML attributes.
File Elements have special notation when you use multiple
file elements or subforms. The File decorator is used by
Zend_Form_Element_File
and allows to set multiple
file elements with only a single methodcall. It is used
automatically and fixes the elements name.
Zend_Form
objects typically need to render an
HTML form tag. The Form decorator proxies to the Form view helper. It
wraps any provided content in an HTML form element, using the
Zend_Form
object's action and method, and any
attributes as HTML attributes.
Forms, display groups, and sub forms are collections of
elements. In order to render these elements, they utilize the
FormElements decorator, which iterates through all items,
calling render()
on each and joining them with the
registered separator. It can either append or prepend content
passed to it.
Some developers and designers prefer to group all error messages at the top of the form. The FormErrors decorator allows you to do this.
By default, the generated list of errors has the following markup:
<ul class="form-errors> <li><b>[element label or name]</b><ul> <li>[error message]</li> <li>[error message]</li> </ul> </li> <li><ul> <li><b>[subform element label or name</b><ul> <li>[error message]</li> <li>[error message]</li> </ul> </li> </ul></li> </ul>
You can pass in a variety of options to configure the generated output:
-
ignoreSubForms: whether or not to disable recursion into subforms. Default value:
FALSE
(i.e., allow recursion). -
markupElementLabelEnd: Markup to append to element labels. Default value: '</b>'
-
markupElementLabelStart: Markup to prepend to element labels. Default value: '<b>'
-
markupListEnd: Markup to append error message lists with. Default value: '</ul>'.
-
markupListItemEnd: Markup to append individual error messages with. Default value: '</li>'
-
markupListItemStart: Markup to prepend individual error messages with. Default value: '<li>'
-
markupListStart: Markup to append error message lists with. Default value: '<ul class="form-errors">'
The FormErrors decorator can either prepend or append the content provided to it.
The HtmlTag decorator allows you to utilize HTML tags to decorate content; the tag utilized is passed in the 'tag' option, and any other options are used as HTML attributes to that tag. The tag by default is assumed to be block level, and replaces the content by wrapping it in the given tag. However, you can specify a placement to append or prepend a tag as well.
The Image decorator allows you to create an HTML image input (<input type="image" ... />), and optionally render it within another HTML tag.
By default, the decorator uses the element's src property, which can
be set with the setImage()
method, as the image
source. Additionally, the element's label will be used as the alt
tag, and the imageValue (manipulated with the Image
element's setImageValue()
and
getImageValue()
accessors) will be used for the value.
To specify an HTML tag with which to wrap the element, either pass a
'tag' option to the decorator, or explicitly call
setTag()
.
Form elements typically have labels, and the Label decorator is
used to render these labels. It proxies to the FormLabel view
helper, and pulls the element label using the
getLabel()
method of the element. If no label is
present, none is rendered. By default, labels are translated when a
translation adapter exists and a translation for the label exists.
You may optionally specify a 'tag' option; if provided, it wraps
the label in that block-level tag. If the 'tag' option is
present, and no label present, the tag is rendered with no
content. You can specify the class to use with the tag with the
'class' option or by calling setTagClass()
.
Additionally, you can specify prefixes and suffixes to use when displaying the element, based on whether or not the label is for an optional or required element. Common use cases would be to append a ':' to the label, or a '*' indicating an item is required. You can do so with the following options and methods:
-
optionalPrefix: set the text to prefix the label with when the element is optional. Use the
setOptionalPrefix()
andgetOptionalPrefix()
accessors to manipulate it. -
optionalSuffix: set the text to append the label with when the element is optional. Use the
setOptionalSuffix()
andgetOptionalSuffix()
accessors to manipulate it. -
requiredPrefix: set the text to prefix the label with when the element is required. Use the
setRequiredPrefix()
andgetRequiredPrefix()
accessors to manipulate it. -
requiredSuffix: set the text to append the label with when the element is required. Use the
setRequiredSuffix()
andgetRequiredSuffix()
accessors to manipulate it.
By default, the Label decorator prepends to the provided content; This can be controlled by specifying one of the following 'placement' options:
-
PREPEND: render the label before the content.
-
APPEND: render the label after the content.
-
IMPLICIT_PREPEND: render the element inside the label tag, placing the label text before the content.
-
IMPLICIT_APPEND: render the element inside the label tag, placing the label text after the content.
Forms, display groups, and sub forms are collections of elements. When using the ViewScript decorator with your form or sub form, it's useful to be able to recursively set the view object, translator, and all fully qualifid names (as determined by sub form array notation). The 'PrepareElements' decorator can do this for you. Typically, you will set it as the first decorator in the list.
$form->setDecorators(array( 'PrepareElements', array('ViewScript', array('viewScript' => 'form.phtml')), ));
The Tooltip decorator translates the title attribute if it is available, if the translator is available and if the translator is not disable on the element being rendered.
Most elements utilize Zend_View
helpers for
rendering, and this is done with the ViewHelper decorator. With
it, you may specify a 'helper' tag to explicitly set the view
helper to utilize; if none is provided, it uses the last segment
of the element's class name to determine the helper, prepending
it with the string 'form': e.g., 'Zend_Form_Element_Text' would
look for a view helper of 'formText'.
Any attributes of the provided element are passed to the view helper as element attributes.
By default, this decorator appends content; use the 'placement' option to specify alternate placement.
Sometimes you may wish to use a view script for creating your elements; this way you can have fine-grained control over your elements, turn the view script over to a designer, or simply create a way to easily override setting based on which module you're using (each module could optionally override element view scripts to suit their own needs). The ViewScript decorator solves this problem.
The ViewScript decorator requires a 'viewScript' option, either provided to the decorator, or as an attribute of the element. It then renders that view script as a partial script, meaning each call to it has its own variable scope; no variables from the view will be injected other than the element itself. Several variables are then populated:
-
element: the element being decorated
-
content: the content passed to the decorator
-
decorator: the decorator object itself
-
Additionally, all options passed to the decorator via
setOptions()
that are not used internally (such as placement, separator, etc.) are passed to the view script as view variables.
As an example, you might have the following element:
// Setting the decorator for the element to a single, ViewScript, // decorator, specifying the viewScript as an option, and some extra // options: $element->setDecorators(array(array('ViewScript', array( 'viewScript' => '_element.phtml', 'class' => 'form element' )))); // OR specifying the viewScript as an element attribute: $element->viewScript = '_element.phtml'; $element->setDecorators(array(array('ViewScript', array('class' => 'form element'))));
You could then have a view script something like this:
<div class="<?php echo $this->class ?>"> <?php echo $this->formLabel($this->element->getName(), $this->element->getLabel()) ?> <?php echo $this->{$this->element->helper}( $this->element->getName(), $this->element->getValue(), $this->element->getAttribs() ) ?> <?php echo $this->formErrors($this->element->getMessages()) ?> <div class="hint"><?php echo $this->element->getDescription() ?></div> </div>
Replacing content with a view script
You may find it useful for the view script to replace the
content provided to the decorator -- for instance, if you want
to wrap it. You can do so by specifying a boolean FALSE
value
for the decorator's 'placement' option:
// At decorator creation: $element->addDecorator('ViewScript', array('placement' => false)); // Applying to an existing decorator instance: $decorator->setOption('placement', false); // Applying to a decorator already attached to an element: $element->getDecorator('ViewScript')->setOption('placement', false); // Within a view script used by a decorator: $this->decorator->setOption('placement', false);
Using the ViewScript decorator is recommended for when you want to have very fine-grained control over how your elements are rendered.