Form API brainstorm

Abstract

Solar needs a helper to facilitate building form templates based on a Solar_Form object. The current Solar_View_Helper_Form is good for automated forms, but not when we need a bit more customized markups. The proposed alternative is a helper based on partials.

Scenario

Our purpose is to take a Solar_Form object $form and build a template to render the field 'my_text' from this form in a view, including its label, description and validation messages. The form object is the following:

$form = Solar::factory('Solar_Form');
$form->setElement('my_text', array(
    'name'  => 'my_text',
    'type'  => 'text',
    'label' => 'MY_TEXT_LABEL',
    'descr' => 'MY_TEXT_DESCR',
));

A quick look at the available options

Option 1: do it manually

The most verbose option is to build the input text manually, which requires a lot of code for a single field. Intentionally, no markup was added in this example:

// Get the element from the form.
$element = $form->elements['my_text'];
 
// Add a label.
echo $this->getText($element['label']);
 
// Is it a required field?
if ($element['require']) {
    echo 'required';
}
 
// Add the input field itself.
echo $this->formText($element);
 
// Add a description.
echo $this->getText($element['descr']);
 
// Add validation messages.
foreach ($element['invalid'] as $invalid) {
    echo $invalid;
}

Option 2: use Solar_View_Helper_Form

Much less code is needed if we use the auto() method from Solar_View_Helper_Form:

$element = $form->elements['my_text'];
echo $this->form()->auto(array($element))->fetch(false);

Problems with this:

  1. it is a bit lenghty and confuse.
  2. we need to 'extract' the element from the Solar_Form object (can't get it directly by its key).
  3. the resulted markup is fixed, as it is hardcoded in the helper.

A mixed alternative: a "free" form helper

A proposed solution is to use a helper that can glue all field pieces using partials, from which you can also get specific info from each form element (label, attributes, messages etc).

Advantages:

  • we can create our own set of partials using any markup and reuse them in many forms.
  • we can freely split / combine forms and mix special markup in a clean way.

Disadvantadges (or the price of the freedom):

  • not as easy to build as an automated form.
  • partials are slower.

Old brainstorm

This is the current API for a form view helper based on templates. The helper is working already, but I'm looking for some feedback about the API. Specially, I would like to know what looks too ugly or could use a better approach. Some features/purposes:

  • No HTML is hardcoded in the form helper.
  • Uses any template set for elements, mixed in the same form.
  • Allows to split the form in multiple parts and mix with HTML.
  • Feedback, labels, descriptions, info etc for each element are available to build the form entirely or partially by hand, if needed.
<?php
// Setup the form helper using a Solar_Form instance.
$form = $this->formSimple($solar_form_instance);
 
// Display form header: form tag, hidden fields and feedback.
echo $form->partial('start');
 
// Display a series of fields.
echo $form
    // Form partials: 
    // * first parameter is the template name
    // * second parameter is an element spec. one of these: 
    //     a) element name
    //     b) array with element names (for groups)
    //     c) Tipos_View_Helper_FormSimpleElement (returned by $form->__call())
    // * third element is the element array name, if any: setting 
    // 'page[name]' as the second parameter is the same as setting 
    // 'name' with 'page' as third parameter.
    ->partial('element', 'page[name]')
    ->partial('element', 'subj', 'page')
    ->partial('differentElementTemplate', 'page[summ]')
    // A form group
    ->partial('group', array('page[checkbox_1]', 'page[checkbox_2]', 'page[checkbox_3]'))
    // An element added on the fly.
    ->partial('element', $form->text(array('name' => 'foo', 'label' => 'bar')))
    ->fetch();
?>
 
<h1>Some text in the middle of the form</h1>
 
<?php
// Display one more element for the same form. No fetch() is needed, as the helper has a __toString() method.
echo $form->partial('element', 'page[body]');
?>
 
</form>
 
brainstorm/form_api.txt · Last modified: 2008/08/25 08:48 (external edit)