Commit | Line | Data |
0abc72ed |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormHandler - Catalyst Tutorial - Chapter 9: Advanced CRUD - FormHandler |
4 | |
0abc72ed |
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 | |
30fc2cda |
58 | This portion of the tutorial explores |
2217b252 |
59 | L<HTML::FormHandler> and how it can be used to manage |
30fc2cda |
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. |
0abc72ed |
63 | |
7ce05098 |
64 | See |
2217b252 |
65 | L<Catalyst::Manual::Tutorial::09_AdvancedCRUD> |
7ce05098 |
66 | for additional form management options other than |
2217b252 |
67 | L<HTML::FormHandler>. |
0abc72ed |
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 | |
7ce05098 |
76 | sudo cpan HTML::FormHandler::Model::DBIC |
0abc72ed |
77 | |
7ce05098 |
78 | It will install L<HTML::FormHandler> as a prerequisite. |
0abc72ed |
79 | |
30fc2cda |
80 | Also, add: |
9372a4db |
81 | |
82 | requires 'HTML::FormHandler::Model::DBIC'; |
83 | |
f4e9de4a |
84 | to your F<Makefile.PL>. |
0abc72ed |
85 | |
86 | =head1 HTML::FormHandler FORM CREATION |
87 | |
7ce05098 |
88 | This section looks at how L<HTML::FormHandler> can be used to |
0abc72ed |
89 | add additional functionality to the manually created form from Chapter 4. |
90 | |
91 | |
7ce05098 |
92 | =head2 Using FormHandler in your controllers |
0abc72ed |
93 | |
433f1ad4 |
94 | FormHandler doesn't have a Catalyst base controller, because interfacing |
0abc72ed |
95 | to a form is only a couple of lines of code. |
96 | |
97 | =head2 Create a Book Form |
98 | |
f4e9de4a |
99 | Create the directory F<lib/MyApp/Form>. Create F<lib/MyApp/Form/Book.pm>: |
0abc72ed |
100 | |
101 | package MyApp::Form::Book; |
9372a4db |
102 | |
0abc72ed |
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 | |
f4e9de4a |
119 | At the top of the F<lib/MyApp/Controller/Books.pm> add: |
0abc72ed |
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; |
8358866c |
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")})); |
0abc72ed |
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 | |
f4e9de4a |
163 | Open F<root/src/books/form.tt2> in your editor and enter the following: |
0abc72ed |
164 | |
165 | [% META title = 'Create/Update Book' %] |
7ce05098 |
166 | |
0abc72ed |
167 | [%# Render the HTML::FormHandler Form %] |
168 | [% form.render %] |
7ce05098 |
169 | |
0abc72ed |
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 | |
f4e9de4a |
175 | Open F<root/src/books/list.tt2> in your editor and add the following to |
0abc72ed |
176 | the bottom of the existing file: |
177 | |
178 | ... |
179 | <p> |
02bb2b5a |
180 | HTML::FormHandler: |
181 | <a href="[% c.uri_for(c.controller.action_for('create')) %]">Create</a> |
0abc72ed |
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" |
7ce05098 |
202 | |
0abc72ed |
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 |
7ce05098 |
208 | integers. |
0abc72ed |
209 | |
210 | |
211 | =head2 Add Constraints |
212 | |
f4e9de4a |
213 | Open F<lib/MyApp/Form/Book.pm> in your editor. |
0abc72ed |
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 |
30fc2cda |
224 | can be set to Multiple to allow the selection of multiple authors; also, make it |
0abc72ed |
225 | required: |
226 | |
9372a4db |
227 | has_field 'authors' => ( type => 'Multiple', label_column => 'last_name', |
228 | required => 1 ); |
0abc72ed |
229 | |
30fc2cda |
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>. |
0abc72ed |
233 | |
234 | =head2 Try Out the Updated Form |
235 | |
7ce05098 |
236 | Press C<Ctrl-C> to kill the previous server instance (if it's still |
0abc72ed |
237 | running) and restart it: |
238 | |
239 | $ script/myapp_server.pl |
240 | |
7ce05098 |
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. |
0abc72ed |
244 | |
245 | =head2 Create the 'edit' method |
246 | |
f4e9de4a |
247 | Edit F<lib/MyApp/Controller/Books.pm> and add the following method: |
0abc72ed |
248 | |
7ce05098 |
249 | |
0abc72ed |
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 | |
f4e9de4a |
262 | Update the F<root/src/books/list.tt2>, adding an 'edit' link below the |
0abc72ed |
263 | "Delete" link to use the FormHandler edit method: |
264 | |
265 | <td> |
02bb2b5a |
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> |
0abc72ed |
270 | </td> |
271 | |
272 | |
273 | =head2 Try Out the Edit/Update Feature |
274 | |
7ce05098 |
275 | Press C<Ctrl-C> to kill the previous server instance (if it's still |
0abc72ed |
276 | running) and restart it: |
277 | |
278 | $ script/myapp_server.pl |
279 | |
7ce05098 |
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 |
0abc72ed |
286 | green. Experiment with other edits to various books. |
287 | |
288 | =head2 See additional documentation on FormHandler |
289 | |
f7f5632e |
290 | L<HTML::FormHandler::Manual> |
0abc72ed |
291 | |
f7f5632e |
292 | L<HTML::FormHandler> |
0abc72ed |
293 | |
294 | #formhandler on irc.perl.org |
295 | |
296 | mailing list: http://groups.google.com/group/formhandler |
297 | |
7ce05098 |
298 | code: http://github.com/gshank/html-formhandler/tree/master |
0abc72ed |
299 | |
300 | =head1 AUTHOR |
301 | |
302 | Gerda Shank, C<gshank@cpan.org> |
303 | |
304 | Copyright 2009, Gerda Shank, Perl Artistic License |