You guys got me thinking about this form builder and now I can't get my mind off it. I've taken a look at Netcarver's and Zend's form classes, and both look awesome. I'm particularly impressed by Netcarver's system and hope to be putting it to use sometime soon.
Focusing on this a lot the last few days also made me realize that a PW formbuilder and the existing Inputfields have a lot of common ground. Enough so that it probably doesn't make sense for a PW formbuilder to venture outside of that. But it does make sense to upgrade PW's Inputfield system to make it more flexible consistent with the needs of a formbuilder. It's easier to maintain and support if there is one system rather than two. It wouldn't replace a system like Netcarver's or Zend's, but would provide a good middle ground for the less complex form needs.
As a first step, I figured I'd see how well Inputfields would adapt for the sort of portability a formbuilder would need. The goal was to be able to take an array or JSON string, and have it render as a form using PW Inputfields, as they are now. This is something I'd not tried before, but the first step we'd need in order to easily store a form schema for a form builder.
A small 20-line recursive function takes that array and dynamically creates a form composed entirely of PW Inputfields. All that's left to do is call $form->render(); I built a small test form and had success with it. Yesterday a friend needed help on a larger form, so decided to put the strategy to work there too. Here is the
result. Not a pretty form by any stretch, but I was happy with how easily it all went together, and now getting me enthusiastic about going further with full blown form builder.
As an example, here's the PHP array schema for my test form:
$formArray = array(
'personal_info' => array(
'type' => 'Fieldset',
'label' => 'Personal Information',
'children' => array(
'first_name' => array(
'type' => 'Text',
'label' => "First Name",
'columnWidth' => 50,
'required' => true,
),
'last_name' => array(
'type' => 'Text',
'label' => "Last Name",
'columnWidth' => 50,
'required' => true
),
'email' => array(
'type' => 'Email',
'label' => "Your Email",
'columnWidth' => 50,
'required' => true
),
'phone' => array(
'type' => 'Text',
'label' => "Your Phone",
'columnWidth' => 50,
'required' => true
)
)
),
'customer_feedback' => array(
'type' => 'Fieldset',
'label' => 'Share Your Feedback',
'children' => array(
'store_location' => array(
'type' => 'Select',
'label' => 'What store location did you visit?',
'options' => array(
'ATL' => 'Atlanta, GA',
'CHI' => 'Chicago, IL',
'NYC' => 'New York, NY',
'SFO' => 'San Francisco, CA'
)
),
'would_visit_again' => array(
'type' => 'Radios',
'label' => 'Would you visit that location again?',
'options' => array(
'Y' => 'Yes I would',
'N' => 'No I would not'
)
),
'comments' => array(
'type' => 'Textarea',
'label' => 'Comments or Questions?',
'description' => "We'll respond right away!",
'rows' => 5
)
)
),
'submit' => array(
'type' => 'Submit',
'value' => 'Submit Your Feedback!'
)
);
That schema can be converted to/from JSON just by calling json_encode/json_decode on it, and gives us exactly the portability I'd want out of it. Given that this can be translated to a full form of Inputfields with a tiny function (arrayToForm), I figured that's a great first step towards an interactive formbuilder. Here's what the template code looks like:
$form = arrayToForm($formArray);
if($form->isSubmitted()) {
$body = "<html><body>" . $form->renderValues() . "</body></html>";
$headers = "Content-type: text/html; charset=utf-8\nFrom: " . $form->get('email')->value;
mail('me@domain.com', 'Form Submission', $body, $headers);
echo "<h2>Thanks, your form was submitted!</h2>";
} else if(count($form->getErrors()) {
echo "<h2>Fix the fields in red and try again.</h2>";
echo $form->render();
} else {
echo $form->render();
}
That's how I'm doing it now, but stuff like the above would obviously be integrated into a FormProcessor class so that you only need to call 1 function to display/process a form, and you could store and browse the results in a DB rather than just emailing it.
Inputfields need to be upgraded so that all the structural markup is customizable. I'd probably want the default render output to be structured around fieldsets rather than lists, and be something that one wouldn't necessarily need any prerequisite CSS/JS except for progressive enhancement. Other upgrades would be more validation options for the basic Inputfields. The nice thing is that any upgrades would benefit all of PW, not just the formbuilder. The next test/proof-of-concept will be to make the creation of that $formArray interactive from the admin (with a Process module).