Default Renderer

Default Renderer – Directly generates HTML using primitive templates

Overview

HTML_QuickForm2_Renderer_Default is essentially a primitive template engine (only supporting blocks and variable placeholders) that is intended for quick prototyping. This Renderer is used under the hood by a magic __toString() method of HTML_QuickForm2_Container (and consequently HTML_QuickForm2 itself). It is similar to HTML_QuickForm_Renderer_Default of HTML_QuickForm though has different template format and more customization possibilities.

Generated HTML is returned by a magic __toString() method, so the renderer can be used in string contexts.

Template syntax

The elements are output in the order they were added using an appropriate template, which looks similar to the following:

<div class="row">
 <p class="label">
  <qf:required><span class="required">*</span></qf:required>
  <qf:label><label for="{id}">{label}</label></qf:label>
 </p>
 <div class="element<qf:error> error</qf:error>">
  <qf:error><span class="error">{error}<br /></span></qf:error>
  {element}
 </div>
</div>

Here {foo} are placeholders that will be replaced by actual element data and <qf:bar>...</qf:bar> are blocks that will be either removed if an element does not have a bar property or will be retained without their <qf:bar> delimiters if said property is present.

The following placeholders are recognized and will be replaced:

{id}
'id' attribute of an element.
{class}
'class' attribute of an element. Mostly needed to put repeat-specific repeatItem and repeatPrototype CSS classes on a outer <div> for a group.
{attributes}
Complete attribute string for an element.
{error}
Error message for an element if it failed validation.
{label}
(Main) label for an element. If an array was passed to setLabel() then this placeholder will be replaced by first element of that array.
{label_more}
Additional label for an element. If an array was passed to setLabel() then it will be replaced by be an element of that array with 'more' key.
{element}
String representation of an element returned by its __toString() method. Only in templates for "scalar" elements.
{content}
Contained elements. Only in templates for Containers.
{hidden}
Collected hidden elements if group_hiddens is on. Only in template for form.
{errors}
Collected form errors if group_errors is on. Only in template for form.
{reqnote}
Required note if form has required elements. Only in template for form.
{message}
Leading and trailing message for grouped errors. Only in template for errors.

The following blocks are possible:

<qf:required>
Block containing the "element is required" mark. Will be kept if an element has a Required Rule attached.
<qf:error>, <qf:label>, <qf:label_more>, <qf:reqnote>, <qf:message>
These blocks usually wrap around placeholders having the same name. In the example above, <qf:error> is also used to set a special CSS class for an invalid element.

Template customization

Form element templates are set by setTemplateForId(), setTemplateForClass(), setElementTemplateForGroupId() and setElementTemplateForGroupClass(). The latter two methods apply to elements that are inside Groups. Note that the word "class" in these method names refers to PHP class name rather than to CSS class name. The renderer will also try going up the class hierarchy, so it will use a template for HTML_QuickForm2_Element to render <input type="text" /> if more specific templates for HTML_QuickForm2_Element_InputText and HTML_QuickForm2_Element_Input are not available.

Another template-related method is setErrorTemplate() which sets templates for errors output when group_errors is TRUE.

When searching for an appropriate template for a given element, the following order is used:

  1. If a template was set for that element by setTemplateForId(), it will be used, no matter if the element belongs to a group or not.
  2. If the element does not belong to a group, templates set via setTemplateForClass() are checked using the element class and going up the class hierarchy.
  3. If the element belongs to a group, templates set by setTemplateForClass() are ignored, instead templates set by setElementTemplateForGroupId() are searched first using the containing group id, then templates set by setElementTemplateForGroupClass() using the containing group class and going up the class hierarchy.
  4. If no template was found on previous steps (which is unlikely as Renderer is set up with default templates), some minimal hardcoded template is used.

Rendering groups

When rendering elements inside Container, two templates are actually used:

  • Container template, having {content} placeholder;
  • Element template.

Elements are first wrapped in their own templates, then {content} placeholder in Container template is replaced by HTML for all contained elements.

This is true for Groups as well, but is less obvious:

  • Default (outer) template for groups looks like template for a scalar element;
  • Default (inner) template for elements inside group is minimal: '{element}'. So you will only get elements' HTML, maybe with separators in between, no additional markup.

The above also means that you will see neither labels for grouped elements, nor their validation errors by default. If you want to output these, you'll need to set a new template for grouped elements using either of setTemplateForId(), setElementTemplateForGroupId(), setElementTemplateForGroupClass():

<?php
// setElementTemplateForGroupId() may be used if you want to customize a specific group
$renderer->setElementTemplateForGroupClass(
    
'HTML_QuickForm2_Container_Group''HTML_QuickForm2_Element',
    
'a complex template with {element}, {label} and {error} placeholders'
);
?>

controller/wizard.php example installed with the package shows setting a complex template for grouped elements.