Constructors of all the elements now have the same list of parameters:
$name
Element name
$attributes
HTML attributes
$data
Additional element-specific data. A 'label'
key in this
array is understood by every element and is used for element's label.
Consequently HTML_QuickForm2_Factory::createElement() and HTML_QuickForm2_Container::addElement() that pass their arguments to the element's constructor have fixed signatures, too.
For example, the following HTML_QuickForm code which adds a radio button and a select element to the form
<?php
$form->addElement('radio', 'iradTest', 'Test Radio Buttons:', 'Check the radio button #1', 1,
array('class' => 'fancyRadio'));
$form->addElement('select', 'iselTest', 'Test Select:', array('A'=>'A', 'B'=>'B', 'C'=>'C', 'D'=>'D'),
array('size' => 3, 'multiple' => 'multiple'));
?>
in HTML_QuickForm2 will be transformed to
<?php
$form->addElement('radio', 'iradTest', array('class' => 'fancyRadio', 'value' => 1),
array('label' => 'Test Radio Buttons:', 'content' => 'Check the radio button #1'));
$form->addElement('select', 'iselTest', array('size' => 3, 'multiple' => 'multiple'),
array('label' => 'Test Select:', 'options' => array('A'=>'A', 'B'=>'B', 'C'=>'C', 'D'=>'D'));
?>
Another possibility is using fluent interfaces
<?php
$form->addElement('radio', 'iradTest', array('value' => 1))
->addClass('fancyRadio')
->setLabel('Test Radio Buttons:')
->setContent('Check the radio button #1');
$form->addElement('select', 'iselTest', array('size' => 3, 'multiple' => 'multiple'))
->setLabel('Test Select:')
->loadOptions(array('A'=>'A', 'B'=>'B', 'C'=>'C', 'D'=>'D'));
?>
which has the benefits of improved readability and code completion in IDEs.
Unlike HTML_QuickForm, where nesting of form elements was limited (elements could be added either
directly to the form or to a group added directly to the form) HTML_QuickForm2 supports unlimited
nesting. Elements that can contain other elements are subclasses of HTML_QuickForm2_Container
which implements DOM-like API: appendChild(), insertBefore(), removeChild(), getElementById(), getElementsByName().
Convenience method addElement() that creates an
element of the given type and adds it to the Container is still available, too. Thanks to
method overloading you can also perform addEltype() calls where
'eltype'
is an element type known to HTML_QuickForm2_Factory:
<?php
$form->addText('testTextBox', array('style' => 'width: 20ex;'));
?>
Note that HTML_QuickForm2 does not use HTML tables for rendering the form, so there is no equivalent to 'header' element of HTML_QuickForm, fieldsets should be used to group form elements. Also there is no special HTML_QuickForm::addGroup(), groups are treated as any other element (addGroup() will work, though, thanks to abovementioned method overloading). Thus code from HTML_QuickForm
<?php
$form->addElement('header', 'personal', 'Personal Information');
$form->addGroup(array(
HTML_QuickForm::createElement('text', 'first', 'First', 'size=10'),
HTML_QuickForm::createElement('text', 'last', 'Last', 'size=10')
), 'name', 'Name:', ', ');
?>
can be changed to the following in HTML_QuickForm2
<?php
$fieldset = $form->addFieldset('personal')->setLabel('Personal Information');
$group = $fieldset->addGroup('name')->setLabel('Name:')->setSeparator(', ');
$group->addText('first', 'size=10', array('label' => 'First'));
$group->addText('last', 'size=10', array('label' => 'Last'));
?>
Elements' incoming values in HTML_QuickForm2 are kept in an array of DataSources, which are searched for a value in the order they were added to the form. A DataSource containing submit values will be added automatically to that list if the form was submitted. The equivalent to HTML_QuickForm::setDefaults() call
<?php
$form->setDefaults(array(
'foo' => 'default foo value',
'bar' => 'default bar value'
));
?>
is the following call to HTML_QuickForm2::addDataSource():
<?php
$form->addDataSource(new HTML_QuickForm2_DataSource_Array(array(
'foo' => 'default foo value',
'bar' => 'default bar value'
)));
?>
It is possible to replace the whole array of form's DataSources using HTML_QuickForm2::setDataSources(), so you can change HTML_QuickForm::setConstants() call
<?php
$form->setConstants(array(
'const' => 'this will override submitted value'
));
?>
to
<?php
$datasources = $form->getDataSources();
array_unshift($datasources, new HTML_QuickForm2_DataSource_Array(array(
'const' => 'this will override submitted value'
)));
$form->setDataSources($datasources);
?>
Here we use the fact that new DataSource will be searched before one containing submitted values, so its values will override submitted ones.
While HTML_QuickForm contained several methods for getting form's and elements' values, HTML_QuickForm2 only has getValue() and getRawValue(), the difference being that the former applies filters to the value and the latter does not. There is no longer a special "submit value" stored separately from form element and returned by HTML_QuickForm::getSubmitValue() / HTML_QuickForm::getSubmitValues().
Calling getValue() on an element returns the element's submit value or NULL for elements that do not currently have a submit value or can not have such a value at all. The value also passes "intrinsic validation" to make sure that it could possibly originate from that element (e.g. select will only return values for options that were added to select). This behaviour is closest to that of old HTML_QuickForm::exportValue().
Calling getValue() on a HTML_QuickForm2 object is equivalent to old HTML_QuickForm::exportValues().
Main differences to filters in HTML_QuickForm:
The following HTML_QuickForm::applyFilter() calls in HTML_QuickForm
<?php
$form->applyFilter('__ALL__', 'trim');
$form->applyFilter('amount', 'intval');
?>
can be converted to the following in HTML_QuickForm2
<?php
$form->addRecursiveFilter('trim');
$amount->addFilter('intval');
?>
Main differences to HTML_QuickForm:
Simple addRule() call in HTML_QuickForm
<?php
$form->addRule('username', 'Username should be at least 5 symbols long', 'minlength', 5, 'client');
?>
can be changed to the following in HTML_QuickForm2
<?php
$username->addRule('minlength', 'Username should be at least 5 symbols long', 5,
HTML_QuickForm2_Rule::CLIENT_SERVER);
?>
There is no longer a special HTML_QuickForm::addGroupRule() method. 'nonempty'
/
'required'
Rule can directly validate a group or other Container making sure
that it contains a given number of nonempty elements, there is also a special
'each'
Rule that applies a given template Rule to each element in a Container.
Thus the following addGroupRule() calls
<?php
$form->addGroupRule('phoneNo', 'Please fill all phone fields', 'required', null, 3, 'client');
$form->addGroupRule('phoneNo', 'Values must be numeric', 'regex', '/^\\d+$/', 3, 'client');
?>
can be changed to
<?php
$phoneNo->addRule('required', 'Please fill all phone fields', 3,
HTML_QuickForm2_Rule::CLIENT_SERVER);
$phoneNo->addRule('each', 'Values must be numeric',
$phoneNo->createRule('regex', '', '/^\\d+$/'),
HTML_QuickForm2_Rule::CLIENT_SERVER);
?>
There is no longer a special addFormRule() method. You can achieve similar behaviour by creating a subclass of HTML_QuickForm2_Rule, implementing its validateOwner() and setOwnerError() methods and adding an instance of that Rule directly to the form:
<?php
class FormRule extends HTML_QuickForm2_Rule
{
protected function validateOwner()
{
$fooValue = $this->owner->getElementById('foo')->getValue();
$barValue = $this->owner->getElementById('bar')->getValue();
return someComplexCheck($fooValue, $barValue);
}
protected function setOwnerError()
{
$this->owner->getElementById('foo')->setError('foo error');
$this->owner->getElementById('bar')->setError('bar error');
}
}
$form->addRule(new FormRule($form));
?>
Note, though, that it may be easier to use Rule chaining instead in most cases.
File
elements no longer require special 'uploadedfile'
and
'filename'
rules, standard 'required'
and
'regex'
can be used (client-side as well).
There is now a javascript library provided with the package which contains code necessary for client-side validation to run. This library should be included in the page if you intend to use client-side validation.
Basic form output in HTML_QuickForm2 is quite easy thanks to a magic __toString() method:
<?php
echo $form;
?>
Under the hood the package uses Renderer setup similar to that of HTML_QuickForm. Currently HTML_QuickForm2 contains ports of Default and Array renderers from HTML_QuickForm, renderers for specific template engines are unlikely to be added to the base package.
Method that accepts a Renderer instance to output the element is now called render() rather than accept() as in HTML_QuickForm.
Default renderer in HTML_QuickForm2 is different from that in HTML_QuickForm:
Consider reviewing the examples installed with the package, they contain useful bits on styling the form.
It is also quite easy to output the form manually by iterating over its elements,
<?php
foreach ($form as $element) {
echo '<label for="' . $element->getId() . '">' . $element->getLabel()
. '</label> ' . $element->__toString() . '<br />';
}
?>
but client-side validation rules are built in the course of the render() call, so there is a special Stub renderer to assist with manual output.
If you are using client-side validation or javascript-backed elements like hierselect or repeat, you should take care that necessary javascript libraries are included in the page before the form. Consult the section on Javascript support.