Quickform2 with Bootstrap compatible Renderer

This is how a QuickForm2 form looks when you use a renderer that produces the markup expected by bootstrap.

x

Alert ! There are errors in your form.

Example form legend
Some value here
Small snippet of help text
Example form legend
Example form legend
Note: Labels surround all the options for much larger click areas and a more usable form.
to All times are shown as Pacific Standard Time (GMT -08:00).
Block of help text to describe the field above if need be.
Note: Labels surround all the options for much larger click areas and a more usable form.

Bootstrap Demo Version

Example form legend
Some value here
Small snippet of help text
Example form legend
@
Example form legend
Note: Labels surround all the options for much larger click areas and a more usable form.
to All times are shown as Pacific Standard Time (GMT -08:00).
Block of help text to describe the field above if need be.
 

The PHP Code

<?php
require_once 'HTML/QuickForm2.php';
require_once 
'HTML/QuickForm2/Renderer.php';

$r HTML_QuickForm2_Renderer::factory('callback');

// Global callback for all the elements

$r->setCallbackForClass('HTML_QuickForm2_Element', function($renderer$element) {
    
$error $element->getError();
    if (
$error) {
        
$html[] = '<div class="clearfix error">';
        
$element->addClass('error');
        
$renderer->errors[] = $error;
    } else {
        
$html[] = '<div class="clearfix">';
    }
    
$html[] = $renderer->renderLabel($element);
    
$html[] = '<div class="input">';
    if (
$element->toggleFrozen()) {
        
$html[] = '<span class="uneditable-input">';
    }
    
$html[] = $element;
    if (
$error) {
        
$html[] = '<span class="help-inline">'.$error.'</span>';
    } else {
        
$label $element->getLabel();
        if (
is_array($label) && !empty($label[1])) {
            
$html[] = '<span class="help-block">'.$label[1].'</span>';
        }
    }
    if (
$element->toggleFrozen()) {
        
$html[] = '</span>';
    }
    
$html[] = '</div>';
    
$html[] = '</div>';
    return 
implode(''$html);
});

// Callback for the error message

$r->setErrorGroupCallback(function($renderer$form) {
    
$html = array();
    if (!empty(
$renderer->errors)) {
        
$html[] = '<div class="alert-message error">';
        
$html[] = '<a class="close" href="#">x</a>';
        
$html[] = '<p>' $renderer->getOption('errors_prefix') . '</p>';
        
$html[] = '</div>';
    }
    return 
implode(""$html);
});

// Callback for groups of checkboxes and radios

$r->setCallbackForClass('InputList', function($renderer$group) {
    
$error $group->getError();
    if (
$error) {
        
$html[] = '<div class="clearfix error">';
        
$renderer->errors[] = $error;
    } else {
        
$html[] = '<div class="clearfix">';
    }
    
$html[] = $renderer->renderLabel($group);
    
$html[] = '<div class="input">';
    
$html[] = '<ul class="inputs-list"><li>';
    
$elements  array_pop($renderer->html);
    
$html[] = implode('</li><li>'$elements);
    
$html[] = '</li></ul>';
    if (
$error) {
        
$html[] = '<span class="help-inline">'.$error.'</span>';
    } else {
        
$label $group->getLabel();
        if (
is_array($label) && !empty($label[1])) {
            
$html[] = '<span class="help-block">'.$label[1].'</span>';
        }
    }
    
$html[] = '</div>';
    
$html[] = '</div>';
    return 
implode(''$html);
});

// Callback for checkboxes and radios inside a group

$r->setElementCallbackForGroupClass('InputList',
    
'HTML_QuickForm2_Element_InputCheckable', function($renderer$element) {
    
$html[] = '<label>';
    
$html[] = '<input' $element->getAttributes(true) . ' /> ';
    
$html[] = $element->getContent();
    
$html[] = '</label>';
    return 
implode(''$html);
});

// Callback for groups of inline inputs

$r->setCallbackForClass('InlineInputs', function($renderer$group) {
    
$error $group->getError();
    if (
$error) {
        
$html[] = '<div class="clearfix error">';
        
$renderer->errors[] = $error;
    } else {
        
$html[] = '<div class="clearfix">';
    }
    
$html[] = $renderer->renderLabel($group);
    
$html[] = '<div class="input">';
    
$html[] = '<div class="inline-inputs">';

    
$separator $group->getSeparator();
    
$elements  array_pop($renderer->html);
    if (!
is_array($separator)) {
        
$content implode((string)$separator$elements);
    } else {
        
$content    '';
        
$cSeparator count($separator);
        for (
$i 0$count count($elements); $i $count$i++) {
            
$content .= (== $i''$separator[($i 1) % $cSeparator]) .
                        
$elements[$i];
        }
    }
    
$html[] = $content;

    if (
$error) {
        
$html[] = '<span class="help-inline">'.$error.'</span>';
    } else {
        
$label $group->getLabel();
        if (
is_array($label) && !empty($label[1])) {
            
$html[] = '<span class="help-block">'.$label[1].'</span>';
        }
    }
    
$html[] = '</div>';
    
$html[] = '</div>';
    
$html[] = '</div>';
    return 
implode(''$html);
});

// Callback for elements inside an inline inputs group

function renderInlineElement($renderer$element) {
    return (string)
$element;
}

$r->setElementCallbackForGroupClass('InlineInputs',
    
'HTML_QuickForm2_Element''renderInlineElement');

// Callback for action inputs

$r->setCallbackForClass('ActionInputs', function($renderer$group) {
    
$html[] = '<div class="actions">';
    
$elements array_pop($renderer->html);
    
$html[] = implode(' '$elements);
    
$html[] = '</div>';
    return 
implode(''$html);
});

// Callback for elements inside an action inputs group
// Note : same as InlineInputs

$r->setElementCallbackForGroupClass('ActionInputs',
    
'HTML_QuickForm2_Element''renderInlineElement');

// Set some options

$r->setOption(array(
    
'group_hiddens' => true,
    
'group_errors'  => false,
    
'required_note' => '<div class="note"><strong>Note:</strong> <span class="required">✱</span> denotes required fields</div>',
    
'errors_prefix' => '<strong>Alert !</strong> There are errors in your form.',
    
'errors_suffix' => '',
));


include 
'quickform2-bootstrap-1.inc.php';
$form = (string)$form->render($r);

?>