3 Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormHandler - Catalyst Tutorial - Chapter 9: Advanced CRUD - FormHandler
7 This is B<Chapter 9 of 10> for the Catalyst tutorial.
9 L<Tutorial Overview|Catalyst::Manual::Tutorial>
15 L<Introduction|Catalyst::Manual::Tutorial::01_Intro>
19 L<Catalyst Basics|Catalyst::Manual::Tutorial::02_CatalystBasics>
23 L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics>
27 L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>
31 L<Authentication|Catalyst::Manual::Tutorial::05_Authentication>
35 L<Authorization|Catalyst::Manual::Tutorial::06_Authorization>
39 L<Debugging|Catalyst::Manual::Tutorial::07_Debugging>
43 L<Testing|Catalyst::Manual::Tutorial::08_Testing>
47 B<09_Advanced CRUD::09_FormHandler>
51 L<Appendices|Catalyst::Manual::Tutorial::10_Appendices>
58 This portion of the tutorial explores
59 L<HTML::FormHandler> and how it can be used to manage
60 forms, perform validation of form input, and save and restore data
61 to or from the database. This was written using HTML::FormHandler version
65 L<Catalyst::Manual::Tutorial::09_AdvancedCRUD>
66 for additional form management options other than
70 =head1 Install HTML::FormHandler
73 Use the following command to install L<HTML::FormHandler::Model::DBIC> directly
76 sudo cpan HTML::FormHandler::Model::DBIC
78 It will install L<HTML::FormHandler> as a prerequisite.
82 requires 'HTML::FormHandler::Model::DBIC';
84 to your F<Makefile.PL>.
86 =head1 HTML::FormHandler FORM CREATION
88 This section looks at how L<HTML::FormHandler> can be used to
89 add additional functionality to the manually created form from Chapter 4.
92 =head2 Using FormHandler in your controllers
94 FormHandler doesn't have a Catalyst base controller, because interfacing
95 to a form is only a couple of lines of code.
97 =head2 Create a Book Form
99 Create the directory F<lib/MyApp/Form>. Create F<lib/MyApp/Form/Book.pm>:
101 package MyApp::Form::Book;
103 use HTML::FormHandler::Moose;
104 extends 'HTML::FormHandler::Model::DBIC';
105 use namespace::autoclean;
107 has '+item_class' => ( default =>'Books' );
109 has_field 'rating' => ( type => 'Integer' );
110 has_field 'authors' => ( type => 'Multiple', label_column => 'last_name' );
111 has_field 'submit' => ( type => 'Submit', value => 'Submit' );
113 __PACKAGE__->meta->make_immutable;
117 =head2 Add Action to Display and Save the Form
119 At the top of the F<lib/MyApp/Controller/Books.pm> add:
121 use MyApp::Form::Book;
123 Add the following methods:
127 Use HTML::FormHandler to create a new book
131 sub create : Chained('base') PathPart('create') Args(0) {
132 my ($self, $c ) = @_;
134 my $book = $c->model('DB::Book')->new_result({});
135 return $self->form($c, $book);
140 Process the FormHandler book form
145 my ( $self, $c, $book ) = @_;
147 my $form = MyApp::Form::Book->new;
149 $c->stash( template => 'books/form.tt2', form => $form );
150 $form->process( item => $book, params => $c->req->params );
151 return unless $form->validated;
152 # Set a status message for the user & return to books list
153 $c->response->redirect($c->uri_for($self->action_for('list'),
154 {mid => $c->set_status_msg("Book created")}));
157 These two methods could be combined at this point, but we'll use the 'form'
158 method later when we implement 'edit'.
161 =head2 Create a Template Page To Display The Form
163 Open F<root/src/books/form.tt2> in your editor and enter the following:
165 [% META title = 'Create/Update Book' %]
167 [%# Render the HTML::FormHandler Form %]
170 <p><a href="[% c.uri_for(c.controller.action_for('list')) %]">Return to book list</a></p>
173 =head2 Add Link for Create
175 Open F<root/src/books/list.tt2> in your editor and add the following to
176 the bottom of the existing file:
181 <a href="[% c.uri_for(c.controller.action_for('create')) %]">Create</a>
184 This adds a new link to the bottom of the book list page that we can
185 use to easily launch our HTML::FormHandler-based form.
188 =head2 Test The HTML::FormHandler Create Form
190 Press C<Ctrl-C> to kill the previous server instance (if it's still
191 running) and restart it:
193 $ script/myapp_server.pl
195 Login as C<test01> (password: mypass). Once at the Book List page,
196 click the new HTML::Formhandler "Create" link at the bottom to display the
197 form. Fill in the following values:
199 Title = "Internetworking with TCP/IP Vol. II"
203 Click the Submit button, and you will be returned to the Book List page
204 with a "Book created" status message displayed.
206 Note that because the 'Author' column is a Select list, only the authors
207 in the database can be entered. The 'ratings' field will only accept
211 =head2 Add Constraints
213 Open F<lib/MyApp/Form/Book.pm> in your editor.
215 Restrict the title size and make it required:
217 has_field 'title' => ( minlength => 5, maxlength => 40, required => 1 );
219 Add range constraints to the 'rating' field:
221 has_field 'rating' => ( type => 'Integer', range_start => 1, range_end => 5 );
223 The 'authors' relationship is a 'many-to-many' pseudo-relation, so this field
224 can be set to Multiple to allow the selection of multiple authors; also, make it
227 has_field 'authors' => ( type => 'Multiple', label_column => 'last_name',
230 Note: FormHandler automatically strips whitespace at the beginning and
231 end of fields. If you want some other kind of stripping (or none) you
232 can specify it explicitly; see L<HTML::FormHandler::Manual>.
234 =head2 Try Out the Updated Form
236 Press C<Ctrl-C> to kill the previous server instance (if it's still
237 running) and restart it:
239 $ script/myapp_server.pl
241 Make sure you are still logged in as C<test01> and try adding a book
242 with various errors: title less than 5 characters, non-numeric rating, a
243 rating of 0 or 6, etc. Also try selecting one, two, and zero authors.
245 =head2 Create the 'edit' method
247 Edit F<lib/MyApp/Controller/Books.pm> and add the following method:
252 Edit an existing book with FormHandler
256 sub edit : Chained('object') PathPart('edit') Args(0) {
257 my ( $self, $c ) = @_;
259 return $self->form($c, $c->stash->{object});
262 Update the F<root/src/books/list.tt2>, adding an 'edit' link below the
263 "Delete" link to use the FormHandler edit method:
266 [% # Add a link to delete a book %]
267 <a href="[% c.uri_for(c.controller.action_for('delete'), [book.id]) %]">Delete</a>
268 [% # Add a link to edit a book %]
269 <a href="[% c.uri_for(c.controller.action_for('edit'), [book.id]) %]">Edit</a>
273 =head2 Try Out the Edit/Update Feature
275 Press C<Ctrl-C> to kill the previous server instance (if it's still
276 running) and restart it:
278 $ script/myapp_server.pl
280 Make sure you are still logged in as C<test01> and go to the
281 L<http://localhost:3000/books/list> URL in your browser. Click the
282 "Edit" link next to "Internetworking with TCP/IP Vol. II", change the
283 rating to a 3, the "II" at end of the title to the number "2", add
284 Stevens as a co-author (control-click), and click Submit. You will then
285 be returned to the book list with a "Book edited" message at the top in
286 green. Experiment with other edits to various books.
288 =head2 See additional documentation on FormHandler
290 L<HTML::FormHandler::Manual>
294 #formhandler on irc.perl.org
296 mailing list: http://groups.google.com/group/formhandler
298 code: http://github.com/gshank/html-formhandler/tree/master
302 Gerda Shank, C<gshank@cpan.org>
304 Copyright 2009, Gerda Shank, Perl Artistic License