3 Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormHandler - Catalyst Tutorial - Chapter 9: Advanced CRUD - FormHandler
8 This is B<Chapter 9 of 10> for the Catalyst tutorial.
10 L<Tutorial Overview|Catalyst::Manual::Tutorial>
16 L<Introduction|Catalyst::Manual::Tutorial::01_Intro>
20 L<Catalyst Basics|Catalyst::Manual::Tutorial::02_CatalystBasics>
24 L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics>
28 L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>
32 L<Authentication|Catalyst::Manual::Tutorial::05_Authentication>
36 L<Authorization|Catalyst::Manual::Tutorial::06_Authorization>
40 L<Debugging|Catalyst::Manual::Tutorial::07_Debugging>
44 L<Testing|Catalyst::Manual::Tutorial::08_Testing>
48 B<09_Advanced CRUD::09_FormHandler>
52 L<Appendices|Catalyst::Manual::Tutorial::10_Appendices>
59 This portion of the tutorial explores
60 L<HTML::FormHandler> and how it can be used to manage
61 forms, perform validation of form input, and save and restore data
62 to or from the database. This was written using HTML::FormHandler version
66 L<Catalyst::Manual::Tutorial::09_AdvancedCRUD>
67 for additional form management options other than
71 =head1 Install HTML::FormHandler
74 Use the following command to install L<HTML::FormHandler::Model::DBIC> directly
77 sudo cpan HTML::FormHandler::Model::DBIC
79 It will install L<HTML::FormHandler> as a prerequisite.
83 requires 'HTML::FormHandler::Model::DBIC';
85 to your C<Makefile.PL>.
87 =head1 HTML::FormHandler FORM CREATION
89 This section looks at how L<HTML::FormHandler> can be used to
90 add additional functionality to the manually created form from Chapter 4.
93 =head2 Using FormHandler in your controllers
95 FormHandler doesn't have a Catalyst base controller, because interfacing
96 to a form is only a couple of lines of code.
98 =head2 Create a Book Form
100 Create the directory C<lib/MyApp/Form>. Create C<lib/MyApp/Form/Book.pm>:
102 package MyApp::Form::Book;
104 use HTML::FormHandler::Moose;
105 extends 'HTML::FormHandler::Model::DBIC';
106 use namespace::autoclean;
108 has '+item_class' => ( default =>'Books' );
110 has_field 'rating' => ( type => 'Integer' );
111 has_field 'authors' => ( type => 'Multiple', label_column => 'last_name' );
112 has_field 'submit' => ( type => 'Submit', value => 'Submit' );
114 __PACKAGE__->meta->make_immutable;
118 =head2 Add Action to Display and Save the Form
120 At the top of the C<lib/MyApp/Controller/Books.pm> add:
122 use MyApp::Form::Book;
124 Add the following methods:
128 Use HTML::FormHandler to create a new book
132 sub create : Chained('base') PathPart('create') Args(0) {
133 my ($self, $c ) = @_;
135 my $book = $c->model('DB::Book')->new_result({});
136 return $self->form($c, $book);
141 Process the FormHandler book form
146 my ( $self, $c, $book ) = @_;
148 my $form = MyApp::Form::Book->new;
150 $c->stash( template => 'books/form.tt2', form => $form );
151 $form->process( item => $book, params => $c->req->params );
152 return unless $form->validated;
153 # Set a status message for the user & return to books list
154 $c->response->redirect($c->uri_for($self->action_for('list'),
155 {mid => $c->set_status_msg("Book created")}));
158 These two methods could be combined at this point, but we'll use the 'form'
159 method later when we implement 'edit'.
162 =head2 Create a Template Page To Display The Form
164 Open C<root/src/books/form.tt2> in your editor and enter the following:
166 [% META title = 'Create/Update Book' %]
168 [%# Render the HTML::FormHandler Form %]
171 <p><a href="[% c.uri_for(c.controller.action_for('list')) %]">Return to book list</a></p>
174 =head2 Add Link for Create
176 Open C<root/src/books/list.tt2> in your editor and add the following to
177 the bottom of the existing file:
182 <a href="[% c.uri_for(c.controller.action_for('create')) %]">Create</a>
185 This adds a new link to the bottom of the book list page that we can
186 use to easily launch our HTML::FormHandler-based form.
189 =head2 Test The HTML::FormHandler Create Form
191 Press C<Ctrl-C> to kill the previous server instance (if it's still
192 running) and restart it:
194 $ script/myapp_server.pl
196 Login as C<test01> (password: mypass). Once at the Book List page,
197 click the new HTML::Formhandler "Create" link at the bottom to display the
198 form. Fill in the following values:
200 Title = "Internetworking with TCP/IP Vol. II"
204 Click the Submit button, and you will be returned to the Book List page
205 with a "Book created" status message displayed.
207 Note that because the 'Author' column is a Select list, only the authors
208 in the database can be entered. The 'ratings' field will only accept
212 =head2 Add Constraints
214 Open C<lib/MyApp/Form/Book.pm> in your editor.
216 Restrict the title size and make it required:
218 has_field 'title' => ( minlength => 5, maxlength => 40, required => 1 );
220 Add range constraints to the 'rating' field:
222 has_field 'rating' => ( type => 'Integer', range_start => 1, range_end => 5 );
224 The 'authors' relationship is a 'many-to-many' pseudo-relation, so this field
225 can be set to Multiple to allow the selection of multiple authors; also, make it
228 has_field 'authors' => ( type => 'Multiple', label_column => 'last_name',
231 Note: FormHandler automatically strips whitespace at the beginning and
232 end of fields. If you want some other kind of stripping (or none) you
233 can specify it explicitly; see L<HTML::FormHandler::Manual>.
235 =head2 Try Out the Updated Form
237 Press C<Ctrl-C> to kill the previous server instance (if it's still
238 running) and restart it:
240 $ script/myapp_server.pl
242 Make sure you are still logged in as C<test01> and try adding a book
243 with various errors: title less than 5 characters, non-numeric rating, a
244 rating of 0 or 6, etc. Also try selecting one, two, and zero authors.
246 =head2 Create the 'edit' method
248 Edit C<lib/MyApp/Controller/Books.pm> and add the following method:
253 Edit an existing book with FormHandler
257 sub edit : Chained('object') PathPart('edit') Args(0) {
258 my ( $self, $c ) = @_;
260 return $self->form($c, $c->stash->{object});
263 Update the C<root/src/books/list.tt2>, adding an 'edit' link below the
264 "Delete" link to use the FormHandler edit method:
267 [% # Add a link to delete a book %]
268 <a href="[% c.uri_for(c.controller.action_for('delete'), [book.id]) %]">Delete</a>
269 [% # Add a link to edit a book %]
270 <a href="[% c.uri_for(c.controller.action_for('edit'), [book.id]) %]">Edit</a>
274 =head2 Try Out the Edit/Update Feature
276 Press C<Ctrl-C> to kill the previous server instance (if it's still
277 running) and restart it:
279 $ script/myapp_server.pl
281 Make sure you are still logged in as C<test01> and go to the
282 L<http://localhost:3000/books/list> URL in your browser. Click the
283 "Edit" link next to "Internetworking with TCP/IP Vol. II", change the
284 rating to a 3, the "II" at end of the title to the number "2", add
285 Stevens as a co-author (control-click), and click Submit. You will then
286 be returned to the book list with a "Book edited" message at the top in
287 green. Experiment with other edits to various books.
289 =head2 See additional documentation on FormHandler
291 L<HTML::FormHandler::Manual>
295 #formhandler on irc.perl.org
297 mailing list: http://groups.google.com/group/formhandler
299 code: http://github.com/gshank/html-formhandler/tree/master
303 Gerda Shank, C<gshank@cpan.org>
305 Copyright 2009, Gerda Shank, Perl Artistic License