1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
|
package HTML::FormHandler::Manual::Intro;
# ABSTRACT: introduction to using FormHandler
__END__
=pod
=encoding UTF-8
=head1 NAME
HTML::FormHandler::Manual::Intro - introduction to using FormHandler
=head1 VERSION
version 0.40057
=head1 SYNOPSIS
L<Manual Index|HTML::FormHandler::Manual>
HTML::FormHandler is a form handling package that validates HTML form data
and, for database forms, saves it to the database on validation.
It has field classes that match various data types and HTML form elements,
and rendering roles that can be used to render forms in many
different ways, from hand-built forms to totally automated rendering.
It can, of course, be used to validate data even if you are not interested
in the rendering capabilities.
A FormHandler 'form' is a Perl subclass of L<HTML::FormHandler> for non-database forms,
or a subclass of L<HTML::FormHandler::Model::DBIC> for database forms, and in
it you define your fields and validation routines. Because it's a Perl class
written in Moose, you have a lot of flexibility and control.
You can validate with Perl methods or Moose type constraints; you can use
your own validation libraries. You can define your own field classes that
perform specialized validation.
When the form is validated, you can get the validated values back with
C<< $form->value >>.
A working example of a Catalyst app using FormHandler forms is available
on github at L<https://github.com/gshank/formhandler-example>.
=head1 Basics
=head2 Create a form class
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 L<HTML::FormHandler::Manual::Fields> for
more information.
=head2 Or create a form class dynamically
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.
=head2 Process the form
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 L<HTML::FormHandler>.
=head2 Or process a database form
A database form inherits from L<HTML::FormHandler::Model::DBIC> instead of
L<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 L<HTML::FormHandler::Manual::Database> and
L<HTML::FormHandler::TraitFor::Model::DBIC>.
=head2 After processing the form
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
C<< $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;
=head2 Rendering the form
At its simplest, all you need to do is C<< $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 C<< $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 L<HTML::FormHandler::Manual::Rendering>.
=head2 Defaults for form fields
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 L<HTML::FormHandler::Manual::Defaults>.
=head2 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 L<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' } ] );
Or use a validate coderef:
has_field 'foo' => ( validate_method => \&check_foo );
sub check_foo {
my $self = shift;
if ( $self->value =~ s/..../ ) {
$self->add_error('....');
}
}
You can also create custom fields with custom validation, or use an
existing field that does the validation you need.
See L<HTML::FormHandler::Manual::Validation> for more information on
validation or L<HTML::FormHandler::Manual::Fields> for more information
on fields.
=head2 Organizing your form code
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' => ( sub => {['MyApp::Form::Field']} );
has_field 'compound1' => ( type => 'Complex' );
has_field 'compound2' => ( type => 'Complex' );
=head2 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 L<HTML::FormHandler::Manual::Testing> for more
information.
=head1 Localization
FormHandler's built-in errors are added to the form fields with
C<< $field->add_error >>, and to the form with C<< $form->add_form_error >>.
These methods call a C<< $self->_localize >> method which is a coderef set from
the field's default_localize sub, the field's 'localize_meth' attribute with
C<< localize_meth => sub {} >>, or a form's sub localize_meth. The default localize
uses Locale::Maketext. You can also use duck_type classes for localization.
See the documentation in L<HTML::FormHandler::TraitFor::I18N> and the tests in xt/locale.t.
If you wish to skip localization for a particular message (such as for system errors)
you can use C<< $field->push_errors >> or C<< $form->push_form_errors >>.
See also L<HTML::FormHandler::TraitFor::I18N>.
=head1 Performance
FormHandler makes heavy use of Moose, so almost all of FormHandler's profiled time
will actually be in Moose methods, mostly constructing form and field attributes.
Some people prefer to use a persistent form class (in a Moose attribute) in order
to skip the form building step on each call. Other people don't like that solution
because state will remain in the form until the next process call. The 'clear'
method is called at the beginning of each 'process', but additional Moose attributes
in the form, etc, will have to cleared by the programmer.
If you are loading options from the database and you don't need to have them refreshed
each time, you can set the 'do_not_reload' flag in the Select/Multiple field.
If you're not using the field widget roles, you can set the 'no_widgets' flag.
If you always use 'process' on each call (recommended) then you can set the
'no_preload' flag in the form to skip building results in BUILD (new).
=head1 AUTHOR
FormHandler Contributors - see HTML::FormHandler
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2014 by Gerda Shank.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
|