Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Form Processing modules

by zby (Vicar)
on Oct 10, 2007 at 17:16 UTC ( #644032=perlmeditation: print w/ replies, xml ) Need Help??

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.

Comment on Form Processing modules
Select or Download Code
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.
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.

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)

      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

        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.

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

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().

      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.

Re: Form Processing modules
by jasonk (Parson) on Oct 11, 2007 at 17:19 UTC
      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.
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.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://644032]
Approved by ikegami
Front-paged by clinton
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2014-10-01 08:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (390 votes), past polls