Release commit for 5.9013
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / 09_AdvancedCRUD / 09_FormHandler.pod
1 =head1 NAME
2
3 Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormHandler - Catalyst Tutorial - Chapter 9: Advanced CRUD - FormHandler
4
5 =head1 OVERVIEW
6
7 This is B<Chapter 9 of 10> for the Catalyst tutorial.
8
9 L<Tutorial Overview|Catalyst::Manual::Tutorial>
10
11 =over 4
12
13 =item 1
14
15 L<Introduction|Catalyst::Manual::Tutorial::01_Intro>
16
17 =item 2
18
19 L<Catalyst Basics|Catalyst::Manual::Tutorial::02_CatalystBasics>
20
21 =item 3
22
23 L<More Catalyst Basics|Catalyst::Manual::Tutorial::03_MoreCatalystBasics>
24
25 =item 4
26
27 L<Basic CRUD|Catalyst::Manual::Tutorial::04_BasicCRUD>
28
29 =item 5
30
31 L<Authentication|Catalyst::Manual::Tutorial::05_Authentication>
32
33 =item 6
34
35 L<Authorization|Catalyst::Manual::Tutorial::06_Authorization>
36
37 =item 7
38
39 L<Debugging|Catalyst::Manual::Tutorial::07_Debugging>
40
41 =item 8
42
43 L<Testing|Catalyst::Manual::Tutorial::08_Testing>
44
45 =item 9
46
47 B<09_Advanced CRUD::09_FormHandler>
48
49 =item 10
50
51 L<Appendices|Catalyst::Manual::Tutorial::10_Appendices>
52
53 =back
54
55
56 =head1 DESCRIPTION
57
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
62 0.28001.
63
64 See
65 L<Catalyst::Manual::Tutorial::09_AdvancedCRUD>
66 for additional form management options other than
67 L<HTML::FormHandler>.
68
69
70 =head1 Install HTML::FormHandler
71
72
73 Use the following command to install L<HTML::FormHandler::Model::DBIC> directly
74 from CPAN:
75
76     sudo cpan HTML::FormHandler::Model::DBIC
77
78 It will install L<HTML::FormHandler> as a prerequisite.
79
80 Also, add:
81
82     requires 'HTML::FormHandler::Model::DBIC';
83
84 to your F<Makefile.PL>.
85
86 =head1 HTML::FormHandler FORM CREATION
87
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.
90
91
92 =head2 Using FormHandler in your controllers
93
94 FormHandler doesn't have a Catalyst base controller, because interfacing
95 to a form is only a couple of lines of code.
96
97 =head2 Create a Book Form
98
99 Create the directory F<lib/MyApp/Form>. Create F<lib/MyApp/Form/Book.pm>:
100
101     package MyApp::Form::Book;
102
103     use HTML::FormHandler::Moose;
104     extends 'HTML::FormHandler::Model::DBIC';
105     use namespace::autoclean;
106
107     has '+item_class' => ( default =>'Books' );
108     has_field 'title';
109     has_field 'rating' => ( type => 'Integer' );
110     has_field 'authors' => ( type => 'Multiple', label_column => 'last_name' );
111     has_field 'submit' => ( type => 'Submit', value => 'Submit' );
112
113     __PACKAGE__->meta->make_immutable;
114     1;
115
116
117 =head2 Add Action to Display and Save the Form
118
119 At the top of the F<lib/MyApp/Controller/Books.pm> add:
120
121    use MyApp::Form::Book;
122
123 Add the following methods:
124
125     =head2 create
126
127     Use HTML::FormHandler to create a new book
128
129     =cut
130
131     sub create : Chained('base') PathPart('create') Args(0) {
132         my ($self, $c ) = @_;
133
134         my $book = $c->model('DB::Book')->new_result({});
135         return $self->form($c, $book);
136     }
137
138     =head2 form
139
140     Process the FormHandler book form
141
142     =cut
143
144     sub form {
145         my ( $self, $c, $book ) = @_;
146
147         my $form = MyApp::Form::Book->new;
148         # Set the template
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")}));
155     }
156
157 These two methods could be combined at this point, but we'll use the 'form'
158 method later when we implement 'edit'.
159
160
161 =head2 Create a Template Page To Display The Form
162
163 Open F<root/src/books/form.tt2> in your editor and enter the following:
164
165     [% META title = 'Create/Update Book' %]
166
167     [%# Render the HTML::FormHandler Form %]
168     [% form.render %]
169
170     <p><a href="[% c.uri_for(c.controller.action_for('list')) %]">Return to book list</a></p>
171
172
173 =head2 Add Link for Create
174
175 Open F<root/src/books/list.tt2> in your editor and add the following to
176 the bottom of the existing file:
177
178     ...
179     <p>
180         HTML::FormHandler:
181         <a href="[% c.uri_for(c.controller.action_for('create')) %]">Create</a>
182     </p>
183
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.
186
187
188 =head2 Test The HTML::FormHandler Create Form
189
190 Press C<Ctrl-C> to kill the previous server instance (if it's still
191 running) and restart it:
192
193     $ script/myapp_server.pl
194
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:
198
199     Title  = "Internetworking with TCP/IP Vol. II"
200     Rating = "4"
201     Author = "Comer"
202
203 Click the Submit button, and you will be returned to the Book List page
204 with a "Book created" status message displayed.
205
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
208 integers.
209
210
211 =head2 Add Constraints
212
213 Open F<lib/MyApp/Form/Book.pm> in your editor.
214
215 Restrict the title size and make it required:
216
217    has_field 'title' => ( minlength => 5, maxlength => 40, required => 1 );
218
219 Add range constraints to the 'rating' field:
220
221    has_field 'rating' => ( type => 'Integer', range_start => 1, range_end => 5 );
222
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
225 required:
226
227    has_field 'authors' => ( type => 'Multiple', label_column => 'last_name',
228                             required => 1 );
229
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>.
233
234 =head2 Try Out the Updated Form
235
236 Press C<Ctrl-C> to kill the previous server instance (if it's still
237 running) and restart it:
238
239     $ script/myapp_server.pl
240
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.
244
245 =head2 Create the 'edit' method
246
247 Edit F<lib/MyApp/Controller/Books.pm> and add the following method:
248
249
250     =head2 edit
251
252     Edit an existing book with  FormHandler
253
254     =cut
255
256     sub edit : Chained('object') PathPart('edit') Args(0) {
257         my ( $self, $c ) = @_;
258
259         return $self->form($c, $c->stash->{object});
260     }
261
262 Update the F<root/src/books/list.tt2>, adding an 'edit' link below the
263 "Delete" link to use the FormHandler edit method:
264
265     <td>
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>
270     </td>
271
272
273 =head2 Try Out the Edit/Update Feature
274
275 Press C<Ctrl-C> to kill the previous server instance (if it's still
276 running) and restart it:
277
278     $ script/myapp_server.pl
279
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.
287
288 =head2 See additional documentation on FormHandler
289
290 L<HTML::FormHandler::Manual>
291
292 L<HTML::FormHandler>
293
294    #formhandler on irc.perl.org
295
296    mailing list: http://groups.google.com/group/formhandler
297
298    code: http://github.com/gshank/html-formhandler/tree/master
299
300 =head1 AUTHOR
301
302 Gerda Shank, C<gshank@cpan.org>
303
304 Copyright 2009, Gerda Shank, Perl Artistic License