=head1 NAME HTML::FormHandler::Manual::Intro - basic usage of FormHandler =head1 SUMMARY HTML::FormHandler is a form handling class primarily useful for getting HMTL form data into the database. It provides attributes on fields that can be used for creating a set of widgets and highly automatic templates, but does not actually create the templates themselves, although there is an example of a rendering role. The DBIC & CDBI models will save form fields automatically to the database, will retrieve selection lists from the database (with type => 'Select' and a fieldname containing a single relationship, or type => 'Multiple' and a many_to_many relationship), and will save the selected values (one value for 'Select', multiple values in a mapping table for a 'Multiple' field). The 'form' is a Perl subclass of L for non-database forms, or a subclass of a model class for database forms, and in it you define your fields (with many possible attributes), and initialization and validation routines. Because it's a Perl class, you have a lot of flexibility. You can define your own L classes to create your own field types, and perform specialized validation. And you can subclass the methods in HTML::FormHandler::Model::DBIC and HTML::FormHandler. The L package includes a working example using a SQLite database and a number of forms in the test directory. You can execute the sample from a downloaded distribution package with: perl -Ilib t/script/bookdb_server.pl =head1 SYNOPSIS To use HTML::FormHandler, you need to create a form class, call the form class from a controller, and choose a method of displaying the form in an HTML page. Create a Form, subclassed from HTML::FormHandler::Model::DBIC package MyApp:Form::User; use Moose; extends 'HTML::FormHandler::Model::DBIC'; # Associate this form with a DBIx::Class result class # Or 'item_class' can be passed in on 'new', or you # you can always pass in a row object has '+item_class' => ( default => 'User' ); # Define the fields that this form will operate on # Field names are usually column, accessor, or relationship names in your # DBIx::Class result class. You can also have fields that don't exist # in your result class. sub profile { # or: has '+profile' => ( default => ...) return { fields => { name => { type => 'Text', label => 'Username', required => 1, required_message => 'You must enter a username', noupdate => 1, unique => 1, # unique in db unique_message => 'That username is already taken' }, age => { type => 'PosInteger', label => 'Age', required => 1, css_class => 'box', # not used by HF, for templates title => 'User age in years', # for templates widget => 'age_text', # allows selecting a particular # widget in your templates or in # a rendering role range_start => 18, # can't enter an age less than 18 }, sex => { type => 'Select', label => 'Gender', required => 1, }, birthdate => '+MyApp::Field::Date', # customized field class hobbies => { type => 'Multiple', size => 5, }, address => 'Text', city => 'Text', state => 'Select', }, dependency => [ ['address', 'city', 'state'], ], }; In a template, for an input field:

[% f = form.field('address') %]

The value can come from the hash returned by $form->fif, from the 'fif' attribute of the field, or can be supplied by FillInForm. Plain HTML works fine for a simple input field if you use FillInForm to supply the value. For a select list, provide a relationship name as the field name, or provide an options_ subroutine in the form. FillInForm alone is not enough for select fields, since you need to access the field 'options'. (field attributes: sort_order, label_column, active_column). TT example:

[% f = form.field('sex') %]

A multiple select list where 'hobbies' is a 'many_to_many' pseudo-relationship. (field attributes: sort_column, label_column, active_column).

[% f = form.field('hobbies') %]

If you always use the same model for your forms, and the same form name space, you can specify the config values in your application module: __PACKAGE__->config( { 'Controller::HTML::FormHandler' => { model_name => 'DB', form_name_space => 'MyApp::Form' }} ); In a Catalyst controller: package MyApp::Controller::User; use Moose; use base 'Catalyst::Controller'; has 'form' => ( isa => 'MyApp::Form::User', is => 'rw', default => sub { MyApp::Form::User->new } ); # Create or edit sub edit : Local { my ( $self, $c, $user_id ) = @_; $c->stash( template => 'user/edit.tt' ); return unless $self->form->process( item_id => $user_id, schema => $c->model('DB::User')->schema ); # Form validated. $c->stash( user => $form->item ); $c->res->redirect($c->uri_for('profile')); } ... With the DBIC model the schema is set from the 'item' (row object) passed in, or from the primary key ('item_id') and schema. The example above uses persistent forms in a Moose attribute. The 'process' method will clear out non-persistent form values and update the information from the database row (if given). If you modify form attributes that are not automatically cleared, you must set those attributes on every request or clear them yourself. You can also create a new form on each request with new: my $form = BookDB::Form::Book->new( item => $book ); return unless $form->process( params => $c->req->parameters ); If you want to use FillInForm to fill in values instead of the field's fif attribute, you will need to set that up yourself in an 'end' routine or a finalize method. One option would be to set the 'fif' hash in a stash variable: my $validated = $self->form->process( ... ); $c->stash( fillinform => $self->form->fif ); return unless $validated; and then check for the stash variable in your end routine and call FillInForm: sub end : Private { my ( $self, $c ) = @_; $c->forward('render') unless $c->res->output; if ($c->stash->{fillinform}) { $c->response->body( HTML::FillInForm->new->fill( scalarref => \$c->response->{body}, fdat => $c->stash->{fillinform}, ) ); } } sub render : ActionClass('RenderView') { } =head1 The Form A "form" class is where fields and validation routines are defined. It is a subclass of a FormHandler model class (for database forms) or FormHandler itself (for non-database forms). Since it is a subclass, many aspects of FormHandler behavior can be changed in a particular form. =head1 Form Models If you are not using a database interface, the base class for your forms is HTML::FormHandler. For use with a database, use a model base class-- a class that knows how to work with your data objects, such as L or L. When using a database model, form field values for the row are retrieved from the database using the field names as database class accessors. FormHandler will use relationships to populate single and multiple selection lists, and validate input. It doesn't yet do anything with other relationships, although it will return a hash of the relationship. You can pass in either the primary key or a row object to the form. If a primary key is passed in, the model will use the item_class (DBIC source name) to fetch the row from the database. The database row is stored in the form's "item" attribute. The C<< $form->process >> or C<< $form->update >> methods will validate the parameters and then update or create the database row object. =head1 The form profile Returns a hashref of field definitions. The possible keys in the profile hashref are: required optional fields auto_required auto_optional dependency The profile is the easiest way to define the fields in your form (though you can also add fields individually). You can categorize your fields as required and optional with two separate hashrefs: my $profile => { required => { field_one => 'Text', }, optional => { field_two => 'Text', }, }; Or you can use one hashref and indicate 'required' as yet another field attribute: my $profile => { fields => [ field_one => { type => 'Text', required => 1 }, field_two => 'Text, ], }; (Making the value of the "fields" key an array allows FormHandler to create the "order" of the fields in the order in which you define them.) The only required key is "type", which determines the field class. All other keys are attributes of L or its subclasses. An example of a select field: my $profile = { fields => { favorite_color => { type => 'Select', label_column => 'color_name', active_column => 'is_active', }, }, }; The definition above is the equivalent of the following code: my $field = HTML::FormHandler::Field::Select->new( name => 'favorite_color', required => 1, label_column => 'color_name', active_column => 'is_active' ); $form->add_field( $field ); For the "auto" profile keys, provide a list of field names. The field types will be determined by calling 'guess_field_type' in the model. auto_required => ['name', 'age', 'sex', 'birthdate'], auto_optional => ['hobbies', 'address', 'city', 'state'], The 'guess_field_type' method could be customized to provide more sophisticated determination of types. See the model class. The 'dependency' profile key is an array of arrays of field names. During validation, if any field in a given group contains the pattern /\S/ (non-blank), the 'required' flag is set for all of the fields in the group. sub profile { return { fields => [ name => 'Text', age => 'Integer', date => 'DateTime', comment => 'Text', ... ], dependency => [ ['address', 'city', 'state', 'zip'], ['cc_no', 'cc_expires'], ], }; } =head1 Fields A form's fields are created from the definitions in the "profile" subroutine. FormHandler processes the profile and creates an array of L objects. The "type" of a field in the profile determines which field class to use. The field class determines which attributes are valid for a particular field. A number of field classes are provided by FormHandler. You can customize the validation in your form on a per field basis, but validation that will be used for more than one field might be more easily handled in a custom field class. Fields can also be added dynamically with the 'add_field' method. In the template the fields are accessed with form.field('name'). Field errors are in $field->errors. Each form field is associated with a general type. The type name is used to load a module by that name: my $profile = { required => { title => 'Text', age => 'Integer', }, }; Type "Text" loads the HTML::FormHandler::Field::Text module and type 'Integer' loads HTML::FormHandler::Field::Integer. The fields are assumed to be in the HTML::FormHandler::Field name space. If you want to explicitly list the field's package, prefix it with a plus sign. The field name space for "+" prefixed fields can be set with the form's "field_name_space" attribute: has '+field_name_space' => ( default => 'MyApp::Form::Field' ); required => { name => 'Text', # HTML::FormHandler::Field::Text foo => '+Foo', # MyApp::Form::Field::Foo }, The most basic type is "Text", which takes a single scalar value. A "Select" class is similar, but its value must be a valid choice from a list of options. A "Multiple" type is like "Select" but it allows selecting more than one value at a time. Each field has a "value" method, which is the field's internal value. This is the value your database object would have (e.g. scalar, boolean 0 or 1, DateTime object). A field's internal value is converted to the external value by use of the field's C< fif_value > method. This method returns a hash which allows a single internal value to be made up of multiple fields externally. For example, a DateTime object internally might be formatted as a day, month, and year externally. When data is passed in to validate the form, it is trimmed of leading and trailing whitespace by the base field class and placed in the field's "input" attribute. Each field has a validate method that validates the input data and then moves it to the internal representation in the "value" attribute. Depending on the model, it's this internal value that is stored or used by your application. By default, the validation is simply to copy the data from the "input" to the "value" field attribute, but you might have a field that must be converted from a text representation to an object (e.g. month, day, year to DateTime). =head1 Other methods for your form =over 4 =item options_$fieldname If you have a 'Select' or 'Multiple' field, there are two ways to provide the 'options', or the list of values and labels for the select list. 1) Get them from a database table (from the relationship that is the field name), or 2) provide them from an options_$fieldname method. An 'options_$fieldname' method should return a list of ordered key (option value) and value (label to be displayed in the select list) pairs. sub options_fruit { return ( 1 => 'apples', 2 => 'oranges', 3 => 'kiwi', ); } You can also write custom methods to retrieve the option info from the database: sub options_country { my $self = shift; my @rows = $self->schema->resultset( 'Country' )-> search( {}, { order_by => ['rank', 'country_name'] } )->all; return [ map { $_->digraph, $_->country_name } @rows ]; } =item init_value_$fieldname Allows you to provide a different initial value for a particular field than that in the database. sub init_value_license { my ( $self, $field, $item ) = @_; return 0 unless $item && $item->license_id; return $item->license_id; } =item validate_$fieldname Do per-field validation customization not handled by the Field class. sub validate_age { my ( $self, $field ) = @_; $field->add_error('Sorry, you must be 18') if $field->value < 18; } =item cross_validate Handle cross-field validation, or any validation that needs to be done after the entire form is validated. This method is executed whether or not the form has validated so far. sub cross_validate { my $self = shift; if ( $self->field('count')->value && $self->field('duration')->value ) { $self->field('duration')->add_error( 'Do not enter both a count and a duration' ); } } =item update_model Override the model's 'update_model' method to do additional updates. sub update_model { my $self = shift; $self->SUPER::update_model; my $event = $self->item; $event->update( ... ); } =back =head1 Filling the HTML form with values There are three ways to get the database or parameter values into the actual HTML form. You can use the field method 'fif' (where "f" is "form.field('book')" ): [% f.fif %] You can use the hash returned by the form method "fif": [% form.fif.book %] Or you can use L and the C<< $form->fif hash >>. If you are already using FormHandler field attributes in your form elements, then using the field 'fif' method is probably easiest. If you are not using FormHandler field attributes, then your choice is between using form.fif and FillInForm. If you are not using FormHandler select lists and you use FillInForm, then it is possible to have FormHandler process HTML forms that have no template references to the form object at all, as long as the field names are correct. If you think that FillInForm is evil, then you could manage with only using FormHandler to fill in the form. =head1 AUTHORS Gerda Shank, gshank@cpan.org =head1 COPYRIGHT This library is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =cut