PageRenderTime 85ms CodeModel.GetById 14ms app.highlight 65ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/HTML/FormHandler/Manual/Intro.pod

http://github.com/gshank/html-formhandler
Unknown | 289 lines | 208 code | 81 blank | 0 comment | 0 complexity | 48e1bb3e678aa9e0055662fba0804680 MD5 | raw file
  1package HTML::FormHandler::Manual::Intro;
  2# ABSTRACT: introduction to using FormHandler
  3
  4=head1 SYNOPSIS
  5
  6L<Manual Index|HTML::FormHandler::Manual>
  7
  8HTML::FormHandler is a form handling package that validates HTML form data
  9and, for database forms, saves it to the database on validation.
 10It has field classes that match various data types and HTML form elements,
 11and rendering roles that can be used to render forms in many
 12different ways, from hand-built forms to totally automated rendering.
 13It can, of course, be used to validate data even if you are not interested
 14in the rendering capabilities.
 15
 16A FormHandler 'form' is a Perl subclass of L<HTML::FormHandler> for non-database forms,
 17or a subclass of L<HTML::FormHandler::Model::DBIC> for database forms, and in
 18it you define your fields and validation routines. Because it's a Perl class
 19written in Moose, you have a lot of flexibility and control.
 20
 21You can validate with Perl methods or Moose type constraints; you can use
 22your own validation libraries. You can define your own field classes that
 23perform specialized validation.
 24
 25When the form is validated, you can get the validated values back with
 26C<< $form->value >>.
 27
 28A working example of a Catalyst app using FormHandler forms is available
 29on github at L<https://github.com/gshank/formhandler-example>.
 30
 31=head1 Basics
 32
 33=head2 Create a form class
 34
 35The most common way of using FormHandler is to create a form package. You
 36must 'use' "HTML::FormHandler::Moose" and 'extend' FormHandler:
 37
 38    package MyApp::Form::Sample;
 39    use HTML::FormHandler::Moose;
 40    extends 'HTML::FormHandler';
 41
 42Then you add some fields with 'has_field', and a field 'type' (the short
 43name of the field package). (Fields with no type have type 'Text'.)
 44
 45    has_field 'foo';
 46    has_field 'bar' => ( type => 'Select' );
 47
 48Basic field types are Text, Select, Checkbox, Submit, Hidden, Reset,
 49TextArea, Password, Upload. See L<HTML::FormHandler::Manual::Fields> for
 50more information.
 51
 52=head2 Or create a form class dynamically
 53
 54You can also create a form class 'dynamically', by creating a 'new'
 55HTML::FormHandler object. Use a 'field_list' parameter to create the fields
 56instead of 'has_field'.
 57
 58    my $form = HTML::FormHandler->new( field_list => [
 59            'username' => { type => 'Text' },
 60            'selections' => { type => 'Select' },
 61        ]
 62    );
 63
 64Some features will not be available using this method (like the automatic
 65use of 'validate_<field_name>' methods) and it's not as easy to test,
 66of course.
 67
 68=head2 Process the form
 69
 70The form's 'process' method should be run on each request, passing in the
 71request parameters:
 72
 73    $form->process( params => $c->request->body_parameters,
 74        action => $action,
 75    );
 76
 77If the parameters are not empty, then validation will be performed. The
 78corollary is that you should not pass in extra parameters when the form
 79has not been posted. A special 'posted' flag can be used if
 80the form consists entirely of fields like checkboxes that do not include
 81names in params if unchecked, and also works to prevent validation from
 82being performed if there are extra params:
 83
 84    $form->process( posted => ( $c->req->method eq 'POST' ),
 85        params => $c->request->parameters, action => $action );
 86
 87There is an alternative method for processing the form, which is sometimes
 88preferred for persistent forms. It returns a 'result' object, and clears
 89the form:
 90
 91    my $result = $form->run( params => $c->request->body_parameters );
 92
 93You can also set most other FormHandler attributes on the 'process' call.,
 94One useful feature is that you can activate or inactivate fields:
 95
 96    $form->process( params => $params, active => ['field1', 'field2'] );
 97
 98See also L<HTML::FormHandler>.
 99
100=head2 Or process a database form
101
102A database form inherits from L<HTML::FormHandler::Model::DBIC> instead of
103L<HTML::FormHandler>. You must either pass in the DBIC row object or give
104FormHandler information to retrieve the row object.
105
106    $form->process( item => $row, params => $params );
107    -- or --
108    $form->process( item_id => $id, schema => $schema,
109        item_class => 'MyRow', params => $params );
110
111'item_class' is often set in the form class.
112
113See also L<HTML::FormHandler::Manual::Database> and
114L<HTML::FormHandler::TraitFor::Model::DBIC>.
115
116=head2 After processing the form
117
118A database form will have saved the data or created a new row, so often no
119more processing is necessary. You can get the structured field values from
120C<< $form->value >>, and do whatever you want with them.
121
122If the validation succeeded, you may want to redirect:
123
124    $form->process( params => $params );
125    return unless $form->validated
126    $c->res->redirect( .... );
127    -- or --
128    return unless $form->process( params => params );
129    $c->res->redirect;
130
131=head2 Rendering the form
132
133At its simplest, all you need to do is C<< $form->render >> in a
134template.
135
136    [% form.render %]
137
138The automatic rendering is powerful and flexible -- you can do almost
139anything with the right settings. Or you can render the form with a
140template.
141
142The form object will give you a hashref of values suitable for
143filling in the form with C<< $form->fif >>.
144
145By default FormHandler structures fields (and renders them) in a way
146that matches the database. If you want to organize the rendering output
147in different ways, you can use blocks to organize your fields.
148
149   has_block 'fieldset1' => ( render_list => ['foo', 'bar'] );
150
151For more rendering info, see L<HTML::FormHandler::Manual::Rendering>.
152
153=head2 Defaults for form fields
154
155The simplest way to provide defaults is by setting the default attribute
156in a field definition:
157
158   has_field 'my_foo' => ( default => 'my_foo' );
159
160The database row ('item') that is passed in will provide initial values
161for the form, of course. You can also provide default values with an
162'init_object', which acts kind of like a database object:
163
164   $form->process( init_object => { foo => '...', bar => '...' } );
165
166There are a number of other flags and methods for providing defaults.
167See L<HTML::FormHandler::Manual::Defaults>.
168
169=head2 Validation
170
171You can validate a field with a method in the form 'validate_<field_name>':
172
173    has_field 'foo';
174    sub validate_foo {
175        my ( $self, $field ) = @_; # self is the form
176        unless( $field->value == .... ) {
177            $field->add_error( .... );
178        }
179    }
180
181You can provide a validation coderef that will be a field method:
182
183    has_field 'foo' => ( validate_method => \&check_foo );
184    sub check_foo {
185        my $self = shift; # self is field
186        unless( $self->value == ... ) {
187            $self->add_error( ... );
188        }
189    }
190
191You can use 'apply' to use Moose types for validation, from L<HTML::FormHandler::Types>
192or another Moose type collection:
193
194    use HTML::FormHandler::Types ('NotAllDigits');
195    ...
196    has_field 'my_field' => ( apply => [NotAllDigits] );
197
198Or create validators with check:
199
200    has_field 'quux' => (
201        apply => [ { check => qr/abc/, message => 'Not a valid quux' } ] );
202
203Or use a validate coderef:
204
205    has_field 'foo' => ( validate_method => \&check_foo );
206    sub check_foo {
207        my $self = shift;
208        if ( $self->value =~ s/..../ ) {
209            $self->add_error('....');
210        }
211    }
212
213You can also create custom fields with custom validation, or use an
214existing field that does the validation you need.
215
216See L<HTML::FormHandler::Manual::Validation> for more information on
217validation or L<HTML::FormHandler::Manual::Fields> for more information
218on fields.
219
220=head2 Organizing your form code
221
222You can use 'has_field' and 'has_block' in Moose roles:
223
224    package MyApp::Form::Role::Address;
225    use HTML::FormHandler::Moose::Role;
226
227    has_field 'foo';
228    has_block 'bar';
229
230Your forms can inherit from base classes that set common application
231defaults. You can override field definitions with '+'.
232
233You can create 'compound' fields and include them in a form:
234
235    package MyApp::Form::Field::Complex;
236    use HTML::FormHandler::Moose;
237    extends 'HTML::FormHandler::Field::Compound';
238    has_field 'field1' => ( validate_method => \&validate_field1 );
239    has_field 'field2' => ( type => 'Select',
240        options_method => \&options_field2 );
241    sub validate_field1 { ... }
242    sub options_field2 { ... }
243    ...
244    package MyApp::Form::Complex;
245    use HTML::FormHandler::Moose;
246    extends 'HTML::FormHandler';
247    has '+field_name_space' => ( default => 'MyApp::Form::Field' );
248    has_field 'compound1' => ( type => 'Complex' );
249    has_field 'compound2' => ( type => 'Complex' );
250
251=head2 Testing
252
253It's much easier to write unit tests for FormHandler forms than for
254Catalyst controllers. The 't' directory of the downloaded distribution
255has lots of examples. See L<HTML::FormHandler::Manual::Testing> for more
256information.
257
258=head1 Localization
259
260FormHandler's built-in errors are added to the form fields with
261C<< $field->add_error >>, and to the form with C<< $form->add_form_error >>.
262These methods call a C<< $self->_localize >> method which is a coderef set from
263the field's default_localize sub, the field's 'localize_meth' attribute with
264C<< localize_meth => sub {} >>, or a form's sub localize_meth. The default localize
265uses Locale::Maketext.  You can also use duck_type classes for localization.
266See the documentation in L<HTML::FormHandler::TraitFor::I18N> and the tests in xt/locale.t.
267
268If you wish to skip localization for a particular message (such as for system errors)
269you can use C<< $field->push_errors >> or C<< $form->push_form_errors >>.
270
271See also L<HTML::FormHandler::TraitFor::I18N>.
272
273=head1 Performance
274
275FormHandler makes heavy use of Moose, so almost all of FormHandler's profiled time
276will actually be in Moose methods, mostly constructing form and field attributes.
277Some people prefer to use a persistent form class (in a Moose attribute) in order
278to skip the form building step on each call. Other people don't like that solution
279because state will remain in the form until the next process call. The 'clear'
280method is called at the beginning of each 'process', but additional Moose attributes
281in the form, etc, will have to cleared by the programmer.
282
283If you are loading options from the database and you don't need to have them refreshed
284each time, you can set the 'do_not_reload' flag in the Select/Multiple field.
285If you're not using the field widget roles, you can set the 'no_widgets' flag.
286If you always use 'process' on each call (recommended) then you can set the
287'no_preload' flag in the form to skip building results in BUILD (new).
288
289=cut