Update: I've made a not exact copy of this page at the p5 wiki (as suggested by Aristotle).
There are many web form processing modules on CPAN - but no one place to compare the features of them. This meditation purpose is to start gathering this comparison information. A wiki page would be more convenient for that - but for now I have no access to some suitable wiki (but as soon as the Catalyst wiki is usable again I'll repost the info there).
I am waiting for suggestions on both how to do this kind of comparison and what to compare. Below is a quick start. I plan to modify this page for a long time.
HTML - HTML generation. It looks like all form processing modules provide validation - so the validation column did not provide any discrimination value and I removed it.
Module name |
Synopsis |
HTML |
Integration with DB |
Form::Processor |
In an application you might want a controller to handle creating and updating a "User" record. And not want to write much code. Here's using Catalyst as an example:
package MyApplication::Controller::User;
use strict;
use MyApplication::Form::User;
sub edit : Local {
my ( $self, $c, $id ) = @_;
# Create the form object
my $form = MyApplication::Form::User->new( $id );
# Update or create the user record if form posted
# and form validates
$form->update_from_from( $c->request->parameters )
if $c->form_posted;
$c->stash->{form} = $form;
}
|
no - but there is a promise of a 'plug-in system' |
Form::Processor::Model::CDBI |
- | - | - |
HTML::FormFu |
use HTML::FormFu;
my $form = HTML::FormFu->new;
$form->load_config_file('form.yml');
$form->process( $cgi_query );
if ( $form->submitted_and_valid ) {
# do something with $form->params
}
else {
# display the form
$template->param( form => $form );
}
|
yes |
DBIx::Class::HTML::FormFu |
- | - | - |
HTML::Widget |
now defunct to be replaced by HTML::FormFu above |
yes |
HTML::Widget::DBIC |
- | - | - |
CGI::Application::Plugin::ValidateRM
|
This only works with CGI::Application - but Data::FormValidator alone can be used outside of it.
# This is the run mode that will be validated. Notice that it accepts
# some errors to be passed in, and on to the template system.
sub form_display {
my $self = shift;
my $errs = shift;
my $t = $self->load_tmpl('page.html');
$t->param($errs) if $errs;
return $t->output;
}
sub form_process {
my $self = shift;
use CGI::Application::Plugin::ValidateRM (qw/check_rm/);
my ($results, $err_page) = $self->check_rm('form_display','_form_pro
+file');
return $err_page if $err_page;
#.. do something with DFV $results object now
my $t = $self->load_tmpl('success.html');
return $t->output;
}
sub _form_profile {
return {
required => 'email',
msgs => {
any_errors => 'some_errors',
prefix => 'err_',
},
};
}
|
yes |
- |
- | - | - |
CGI::FormBuilder |
use CGI::FormBuilder;
# Assume we did a DBI query to get existing values
my $dbval = $sth->fetchrow_hashref;
# First create our form
my $form = CGI::FormBuilder->new(
name => 'acctinfo',
method => 'post',
stylesheet => '/path/to/style.css',
values => $dbval, # defaults
);
# Now create form fields, in order
# FormBuilder will automatically determine the type for you
$form->field(name => 'fname', label => 'First Name');
$form->field(name => 'lname', label => 'Last Name');
# Setup gender field to have options
$form->field(name => 'gender',
options => [qw(Male Female)] );
# Include validation for the email field
$form->field(name => 'email',
size => 60,
validate => 'EMAIL',
required => 1);
# And the (optional) phone field
$form->field(name => 'phone',
size => 10,
validate => '/^1?-?\d{3}-?\d{3}-?\d{4}$/',
comment => '<i>optional</i>');
# Check to see if we're submitted and valid
if ($form->submitted && $form->validate) {
# Get form fields as hashref
my $field = $form->fields;
# Do something to update your data (you would write this)
do_data_update($field->{lname}, $field->{fname},
$field->{email}, $field->{phone},
$field->{gender});
# Show confirmation screen
print $form->confirm(header => 1);
} else {
# Print out the form
print $form->render(header => 1);
}
|
yes |
no |
Updates:
- Added CGI::Application::Plugin::ValidateRM and CGI::FormBuilder.
- Removed column Validation - validation looks like a requirement here.
Re: Form Processing modules
by perrin (Chancellor) on Oct 10, 2007 at 19:40 UTC
|
The most impressive one I've seen is CGI::Application::Plugin::ValidateRM. It checks the input with Data::FormValidator and then redisplays the form with the errors and the input values refilled by HTML::FillInForm if it fails. Here's an example:
# This is the run mode that will be validated. Notice that it accepts
# some errors to be passed in, and on to the template system.
sub form_display {
my $self = shift;
my $errs = shift;
my $t = $self->load_tmpl('page.html');
$t->param($errs) if $errs;
return $t->output;
}
sub form_process {
my $self = shift;
use CGI::Application::Plugin::ValidateRM (qw/check_rm/);
my ($results, $err_page) = $self->check_rm('form_display','_form_pro
+file');
return $err_page if $err_page;
#.. do something with DFV $results object now
my $t = $self->load_tmpl('success.html');
return $t->output;
}
sub _form_profile {
return {
required => 'email',
msgs => {
any_errors => 'some_errors',
prefix => 'err_',
},
};
}
The other that looks interesting is Rose-HTML-Objects. | [reply] [d/l] |
Re: Form Processing modules
by LTjake (Prior) on Oct 10, 2007 at 22:25 UTC
|
I've not used them, but it might be worth adding:
-- "Go up to the next female stranger you see and tell her that her "body is a wonderland."
My hypothesis is that she’ll be too busy laughing at you to even bother slapping you." (src)
| [reply] |
|
A complete sidebar, but something for the people reading this. There are other things that are somewhat app-specific, but have some good points that can be built upon or even just taken if the license permits.
I hate tooting my own horn, but a few people have found it worth stealing for their projects: Mango::Form. It uses a hybrid config of CGI::FormBuilder for the form definitions with FormValidator::Simple config for the validation all in the same config file. The CGI::FB validation wasn't as good as FV::S for me, so the two got married together.
---
name: myform
method: POST
javascript: 0
stylesheet: 1
sticky: 1
submit: LABEL_CREATE
fields:
- sku:
type: text
size: 25
maxlength: 25
constraints:
- NOT_BLANK
- LENGTH, 1, 25
- UNIQUE
- name:
type: text
size: 25
maxlength: 25
constraints:
- NOT_BLANK
- LENGTH, 1, 25
| [reply] [d/l] |
|
I'm sorry, I'm AM self-whoring now. :-)
I should also mention, and I think this is an important thing to list on all of the modules above, is support for message/error/label localization, both internally in the modules, or externally via callbacks or something.
In the case of Mango::Form, labels default LABEL_FIELDNAME and error messages default to FIELD_CONSTRAINTNAME. These can be overriden in the config above, but are all mostly passed through L18N like Maketext, or the Catalyst::Plugin::L10N or other such things.
Once people find a good form handler, then a good validator, the next things that usually bites is the localization of grouping of the messages themselves.
| [reply] |
Re: Form Processing modules
by hossman (Prior) on Oct 10, 2007 at 20:58 UTC
|
i would suggest that if you're going to put code tags in a table cell, trim all uniform leading whitespace -- top level lines can be in column 1 -- and use 2 psace "tabing" instead of 4.
I'm not trying to start a holy war of general code formatting or anything here, i'm just saying: if you want to put code in a little box, don't make it any wider then it has to be.
| [reply] |
Re: Form Processing modules
by jgottshall (Initiate) on Oct 11, 2007 at 16:08 UTC
|
Glad someone is taking this on. Can't wait to see it on the wiki. Some other possible points of comparison:
- validation
- does the package provide it's own system of validation rules, and if so, is the system customizable/extensible?
- does the package support one or more third-party validation packages, and if so, which ones?
- form construction/definition
- does the package support config-file-based form construction?
- does the package support dynamic (run-time) form construction/modification?
- framework integration (e.g. CGI::App, Catalyst, etc.)
I second perrin's suggestion to review Rose::HTML::Form from the Rose::HTML::Objects dist. I haven't used it yet, but from what I've seen it has some unique and interesting features:
- form classes can include code for pre- and post-processing; you can embed methods to populate the form from objects and/or construct objects from submitted data, or you can embed your model/db interactions directly
- forms can be nested/aggregated with automatic fieldname subscripting; e.g. you can design a PersonForm for name info and an AddressForm for contact info, then display and process them as a single submission
- basic field types (e.g. checkbox groups, selectboxes) can be subclassed to create reusable custom field types with their own specific validation, input and output filtering, and even compounding of multiple sub-fields
| [reply] |
Re: Form Processing modules
by moseley (Acolyte) on Oct 11, 2007 at 16:42 UTC
|
As the author of Form::Processor I wanted to add a few comments.
Form::Processor is new to CPAN and still has some rough edges, of course, and
won't tickle everyone's fancy. After all, it's just code I was using in my own projects.
But, I'd love to have help extending it -- for example in adding a DBIC model class in addition to the existing CDBI model class.
(Better docs might not be a bad idea, either...)
First, Catalyst users may wish to look at the plugin
Catalyst::Plugin::Form::Processor which simplifies things a bit.
There's also a sample application included that makes it easy to try the
module.
That plugin demonstrates the concept of the module -- that forms are objects
and that the form should know how to populate itself from the database (including
valid options), how to validate itself, and how to create or update data in a database.
I really don't want to be bothered with that in the application code (e.g. in
a controller). For example:
sub edit : Local {
my ( $self, $c, $user_id ) = @_;
# Validate and insert/update database
# simply display form (again) if does not validate
return unless $c->update_from_form( $user_id );
$c->post_redirect('list', 'User updated' );
}
Second, the review says Form::Processor does not generate HTML. That is true,
but it's also by design as my interest was in moving data back and forth
between the user and a database, not so much in displaying forms (HTML or otherwise).
That said, there is an included example TT file that will generate the HTML in the Catalyst Plugin.
I find it very rare that forms
are so basic that they can be completely auto-generated. It's like scaffolding:
great to demonstrate something quickly but not so useful when you get into the
realities of an application.
Where validation messages appear, label layout, javascript validation,
localization (although error message localization is supported), etc. are all display issues so I wanted to leave that to the
template system and CSS. And frankly, it's just not that hard to generate the
html.
Form::Processor is based on the design of Rose::HTML::Objects.
I recommend checking out that module. But, again, that module tends to focus
more on the HTML side than the database side. But, John does amazing work
and I really think anyone looking at form processing should consider that module.
Similar to Rose::HTML::Objects, in Form::Processor the forms
are objects as well as the individual fields. Fields can be sub-classed, of course, so new
fields can be created based on existing fields. The idea is that your application
probably has specific data types that are used in multiple places so it's expected that
custom fields would be created for each application. Fields can also be (contain) forms,
which is one way to create
compound fields. That means you can also build forms from other forms, but I've rarely needed
to do that. (It's a bit kludgy, but has worked ok so far.)
Finally, I've never been sold on the configuration file-driven forms, such as describing the forms
in YAML. Works for the general case, but my forms almost always have custom validation
needs, custom option population, special needs when fetching or updating data from the
database, etc. Kind of hard to describe in a config file.
Having each form as a separate module solves that, plus it keeps everything form-related in one
place. That said, if your forms are trivially simple
(just simple create/update without any extra validation needed), building forms from YAML would be
just a few lines of code. For simple forms I just pass in the form structure when calling new().
| [reply] [d/l] |
|
Replying to all mentioning Rose::HTML::Objects - it is on my task list (but if someone would create that table row table for me I would just include it - this might be faster :).
Ad HTML generation (and configs ) - don't be defensive here - there are people with similar views as yours and for them no HTML generation (or configs) would be a feature.
By the way I really like the brevity of the Catalyst controllers using Form::Process - thumbs up.
| [reply] |
Re: Form Processing modules
by jasonk (Parson) on Oct 11, 2007 at 17:19 UTC
|
| [reply] |
|
Updated - thanks. I don't like the fact that it requires that you add form related code to the database - that's probably why I forgot about it.
| [reply] |
Re: Form Processing modules
by Aristotle (Chancellor) on Oct 14, 2007 at 19:17 UTC
|
A wiki page would be more convenient for that – but for now I have no access to some suitable wiki
Try the Perl 5 wiki. It already has an overview page with lists of Recommended CPAN modules, such as the various Web Frameworks. An overview of form processors like yours would fit right in.
Makeshifts last the longest.
| [reply] |
|
|