Createaformclass
The most common way of using FormHandler is to create a form package. You must 'use'
"HTML::FormHandler::Moose" and 'extend' FormHandler:
package MyApp::Form::Sample;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler';
Then you add some fields with 'has_field', and a field 'type' (the short name of the field package).
(Fields with no type have type 'Text'.)
has_field 'foo';
has_field 'bar' => ( type => 'Select' );
Basic field types are Text, Select, Checkbox, Submit, Hidden, Reset, TextArea, Password, Upload. See
HTML::FormHandler::Manual::Fields for more information.
Orcreateaformclassdynamically
You can also create a form class 'dynamically', by creating a 'new' HTML::FormHandler object. Use a
'field_list' parameter to create the fields instead of 'has_field'.
my $form = HTML::FormHandler->new( field_list => [
'username' => { type => 'Text' },
'selections' => { type => 'Select' },
]
);
Some features will not be available using this method (like the automatic use of 'validate_<field_name>'
methods) and it's not as easy to test, of course.
Processtheform
The form's 'process' method should be run on each request, passing in the request parameters:
$form->process( params => $c->request->body_parameters,
action => $action,
);
If the parameters are not empty, then validation will be performed. The corollary is that you should not
pass in extra parameters when the form has not been posted. A special 'posted' flag can be used if the
form consists entirely of fields like checkboxes that do not include names in params if unchecked, and
also works to prevent validation from being performed if there are extra params:
$form->process( posted => ( $c->req->method eq 'POST' ),
params => $c->request->parameters, action => $action );
There is an alternative method for processing the form, which is sometimes preferred for persistent
forms. It returns a 'result' object, and clears the form:
my $result = $form->run( params => $c->request->body_parameters );
You can also set most other FormHandler attributes on the 'process' call., One useful feature is that you
can activate or inactivate fields:
$form->process( params => $params, active => ['field1', 'field2'] );
See also HTML::FormHandler.
Orprocessadatabaseform
A database form inherits from HTML::FormHandler::Model::DBIC instead of HTML::FormHandler. You must
either pass in the DBIC row object or give FormHandler information to retrieve the row object.
$form->process( item => $row, params => $params );
-- or --
$form->process( item_id => $id, schema => $schema,
item_class => 'MyRow', params => $params );
'item_class' is often set in the form class.
See also HTML::FormHandler::Manual::Database and HTML::FormHandler::TraitFor::Model::DBIC.
Afterprocessingtheform
A database form will have saved the data or created a new row, so often no more processing is necessary.
You can get the structured field values from "$form->value", and do whatever you want with them.
If the validation succeeded, you may want to redirect:
$form->process( params => $params );
return unless $form->validated
$c->res->redirect( .... );
-- or --
return unless $form->process( params => params );
$c->res->redirect;
Renderingtheform
At its simplest, all you need to do is "$form->render" in a template.
[% form.render %]
The automatic rendering is powerful and flexible -- you can do almost anything with the right settings.
Or you can render the form with a template.
The form object will give you a hashref of values suitable for filling in the form with "$form->fif".
By default FormHandler structures fields (and renders them) in a way that matches the database. If you
want to organize the rendering output in different ways, you can use blocks to organize your fields.
has_block 'fieldset1' => ( render_list => ['foo', 'bar'] );
For more rendering info, see HTML::FormHandler::Manual::Rendering.
Defaultsforformfields
The simplest way to provide defaults is by setting the default attribute in a field definition:
has_field 'my_foo' => ( default => 'my_foo' );
The database row ('item') that is passed in will provide initial values for the form, of course. You can
also provide default values with an 'init_object', which acts kind of like a database object:
$form->process( init_object => { foo => '...', bar => '...' } );
There are a number of other flags and methods for providing defaults. See
HTML::FormHandler::Manual::Defaults.
Validation
You can validate a field with a method in the form 'validate_<field_name>':
has_field 'foo';
sub validate_foo {
my ( $self, $field ) = @_; # self is the form
unless( $field->value == .... ) {
$field->add_error( .... );
}
}
You can provide a validation coderef that will be a field method:
has_field 'foo' => ( validate_method => \&check_foo );
sub check_foo {
my $self = shift; # self is field
unless( $self->value == ... ) {
$self->add_error( ... );
}
}
You can use 'apply' to use Moose types for validation, from HTML::FormHandler::Types or another Moose
type collection:
use HTML::FormHandler::Types ('NotAllDigits');
...
has_field 'my_field' => ( apply => [NotAllDigits] );
Or create validators with check:
has_field 'quux' => (
apply => [ { check => qr/abc/, message => 'Not a valid quux' } ] );
You can also create custom fields with custom validation, or use an existing field that does the
validation you need.
See HTML::FormHandler::Manual::Validation for more information on validation or
HTML::FormHandler::Manual::Fields for more information on fields.
Organizingyourformcode
You can use 'has_field' and 'has_block' in Moose roles:
package MyApp::Form::Role::Address;
use HTML::FormHandler::Moose::Role;
has_field 'foo';
has_block 'bar';
Your forms can inherit from base classes that set common application defaults. You can override field
definitions with '+'.
You can create 'compound' fields and include them in a form:
package MyApp::Form::Field::Complex;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Compound';
has_field 'field1' => ( validate_method => \&validate_field1 );
has_field 'field2' => ( type => 'Select',
options_method => \&options_field2 );
sub validate_field1 { ... }
sub options_field2 { ... }
...
package MyApp::Form::Complex;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler';
has '+field_name_space' => ( default => 'MyApp::Form::Field' );
has_field 'compound1' => ( type => 'Complex' );
has_field 'compound2' => ( type => 'Complex' );
Testing
It's much easier to write unit tests for FormHandler forms than for Catalyst controllers. The 't'
directory of the downloaded distribution has lots of examples. See HTML::FormHandler::Manual::Testing for
more information.