Fix date
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / AdvancedCRUD / FormFu.pod
1 =head1 NAME
2
3 Catalyst::Manual::Tutorial::AdvancedCRUD::FormFu - Catalyst Tutorial - Part 9: Advanced CRUD - FormFu
4
5
6 NOTE:  This part of the tutorial is in progress and will be ready soon.
7
8 =head1 OVERVIEW
9
10 This is B<Part 9 of 10> for the Catalyst tutorial.
11
12 L<Tutorial Overview|Catalyst::Manual::Tutorial>
13
14 =over 4
15
16 =item 1
17
18 L<Introduction|Catalyst::Manual::Tutorial::Intro>
19
20 =item 2
21
22 L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
23
24 =item 3
25
26 L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics>
27
28 =item 4
29
30 L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
31
32 =item 5
33
34 L<Authentication|Catalyst::Manual::Tutorial::Authentication>
35
36 =item 6
37
38 L<Authorization|Catalyst::Manual::Tutorial::Authorization>
39
40 =item 7
41
42 L<Debugging|Catalyst::Manual::Tutorial::Debugging>
43
44 =item 8
45
46 L<Testing|Catalyst::Manual::Tutorial::Testing>
47
48 =item 9
49
50 B<Advanced CRUD>
51
52 =item 10
53
54 L<Appendices|Catalyst::Manual::Tutorial::Appendices>
55
56 =back
57
58
59 =head1 DESCRIPTION
60
61 This portion of the tutorial explores L<HTML::FormFu|HTML::FormFu> and 
62 how it can be used to manage forms, perform validation of form input, 
63 as well as save and restore data to/from the database.
64
65 See 
66 L<Catalyst::Manual::Tutorial::AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
67 for additional form management options other than 
68 L<HTML::FormFu|HTML::FormFu>.
69
70
71 =head1 Install C<HTML::FormFu>
72
73 If you are following along in Ubuntu, it turns out that C<HTML::FormFu> 
74 is not yet available as a package at the time this was written.  To 
75 install it with a combination of C<apt-get> packages and traditional 
76 CPAN modules, first use C<apt-get> to install most of the modules 
77 required by C<HTML::FormFu>:
78
79     sudo apt-get install libtest-nowarnings-perl libdatetime-format-builder-perl \
80     libdatetime-format-strptime-perl libdatetime-locale-perl \
81     libhtml-tokeparser-simple-perl liblist-moreutils-perl \
82     libregexp-copy-perl libregexp-common-perl libyaml-syck-perl libparams-util-perl
83
84 Then use the following command to install directly from CPAN the modules 
85 that aren't available as Ubuntu/Debian packages via C<apt-get>:
86
87     sudo cpan File::ShareDir Task::Weaken Config::Any HTML::FormFu \
88     Catalyst::Controller::HTML::FormFu
89
90
91 =head1 C<HTML::FormFu> FORM CREATION
92
93 This section looks at how L<HTML::FormFu|HTML::FormFu> can be used to 
94 add additional functionality to the manually created form from Part 4.
95
96
97 =head2 Inherit From C<Catalyst::Controller::HTML::FormFu>
98
99 First, change your C<lib/MyApp/Controller/Books.pm> to inherit from
100 L<Catalyst::Controller::HTML::FormFu|Catalyst::Controller::HTML::FormFu>
101 by changing the C<use base> line from the default of:
102
103     use base 'Catalyst::Controller';
104
105 to use the FormFu base controller class:
106
107     use base 'Catalyst::Controller::HTML::FormFu';
108
109
110 =head2 Add Action to Display and Save the Form
111
112 Open C<lib/MyApp/Controller/Books.pm> in your editor and add the
113 following method:
114
115     =head2 fu_form_create
116     
117     Build an HTML::FormFu form for book creation and updates
118     
119     =cut
120     
121     sub fu_form_create :Local :FormConfig {
122         my ($self, $c) = @_;
123     
124         # Get the form that the :FormConfig attribute saved in the stash
125         my $form = $c->stash->{form};
126   
127         # Check if the form as been submitted (vs. displaying the initial
128         # form) and if the data based validation.  "submitted_and_valid"
129         # is shorthand for "$form->submitted && !$form->has_errors"
130         if ($form->submitted_and_valid) {
131             # Create a new book
132             my $book = $c->model('DB::Books')->new_result({});
133             # Save the form data for the book
134             $form->save_to_model($book);
135             # Set a status message for the user
136             $c->flash->{status_msg} = 'Book created';
137             # Return to the books list
138             $c->response->redirect($c->uri_for('list')); 
139             $c->detach;
140         } else {
141             # Get the authors from the DB
142             my @authorObjs = $c->model("DB::Authors")->all();
143             # Create an array of arrayrefs where each arrayref is an author
144             my @authors;
145             foreach (sort {$a->last_name cmp $b->last_name} @authorObjs) {
146                 push(@authors, [$_->id, $_->last_name]);
147             }
148             # Get the select added by the config file
149             my $select = $form->get_element({type => 'Select'});
150             # Add the authors to it
151             $select->options(\@authors);
152         }
153         
154         # Set the template
155         $c->stash->{template} = 'books/fu_form_create.tt2';
156     }
157
158
159 =head2 Create a Form Config File
160
161 Although C<HTML::FormFu> supports any configuration file handled by
162 L<Config::Any|Config::Any>, most people tend to use YAML.  First
163 create a directory to hold your form configuration files:
164
165     mkdir -p root/forms/books
166
167 Then create the file C<root/forms/books/fu_form_create.yml> and enter the 
168 following text:
169
170     ---
171     # indicator is the field that is used to test for form submission
172     indicator: submit
173     # Start listing the form elements
174     elements:
175         # The first element will be a text field for the title
176         - type: Text
177           name: title
178           label: Title
179           # This is an optional 'mouse over' title pop-up
180           attributes:
181             title: Enter a book title here
182         - type: Text
183           name: rating
184           label: Rating
185           attributes:
186             title: Enter a rating between 1 and 5 here
187         # The submit button
188         - type: Submit
189           name: submit
190           value: Submit
191
192
193 =head2 Update the CSS
194
195 Edit C<root/src/ttsite.css> and add the following lines to the bottom of
196 the file:
197
198     label {
199         display: block;
200     }
201     .submit {
202         display: block;
203     }
204     .error_messages {
205         color: [% site.col.error %];
206     }
207
208 These changes will display form elements vertically and also show error
209 messages in red.  Note that we are pulling the color scheme settings
210 from the C<root/lib/config/col> file that was created by the TTSite
211 helper.  This allows us to change the color used by various error styles
212 in the CSS from a single location.
213
214
215 =head2 Create a Template Page To Display The Form
216
217 Open C<root/src/books/fu_form_create.tt2> in your editor and enter the following:
218
219     [% META title = 'Create/Update Book' %]
220     
221     [%# Render the HTML::FormFu Form %]
222     [% form %]
223     
224     <p><a href="[% Catalyst.uri_for('list') %]">Return to book list</a></p>
225
226
227 =head2 Add Links for Create and Update via C<HTML::FormFu>
228
229 Open C<root/src/books/list.tt2> in your editor and add the following to
230 the bottom of the existing file:
231
232     <p>
233       HTML::FormFu:
234       <a href="[% Catalyst.uri_for('fu_form_create') %]">Create</a>
235     </p>
236
237
238 =head2 Test The <HTML::Widget> Create Form
239
240 Press C<Ctrl-C> to kill the previous server instance (if it's still
241 running) and restart it:
242
243     $ script/myapp_server.pl
244
245 Login as C<test01>.  Once at the Book List page, click the HTML::FormFu 
246 "Create" link to display for form produced by C<make_book_widget>.  Fill 
247 out the form with the following values: Title = "Internetworking with 
248 TCP/IP Vol. II", Rating = "4", and Author = "Comer".  Click Submit, and 
249 you will be returned to the Book List page with a "Book created" status 
250 message displayed.
251
252 Also note that this implementation allows you to can create books with
253 bogus information.  Although we have constrained the authors with the
254 drop-down list, there are no restrictions on items such as the length of
255 the title (for example, you can create a one-letter title) and value for
256 the rating (you can use any number you want, and even non-numeric values
257 with SQLite).  The next section will address this concern.
258
259 B<Note:> Depending on the database you are using and how you established
260 the columns in your tables, the database could obviously provide various
261 levels of "type enforcement" on your data.  The key point being made in
262 the previous paragraph is that the I<web application> itself is not
263 performing any validation.
264
265
266 =head1 C<HTML::FormFu> VALIDATION AND FILTERING
267
268 Although the use of L<HTML::FormFu|HTML::FormFu> in the previous section
269 did provide an automated mechanism to build the form, the real power of
270 this module stems from functionality that can automatically validate and
271 filter the user input.  Validation uses constraints to be sure that
272 users input appropriate data (for example, that the email field of a
273 form contains a valid email address).  Filtering can be used to remove
274 extraneous whitespace from fields or to escape meta-characters in user
275 input.
276
277 =head2 Add Constraints
278
279
280 Open C<root/forms/books/fu_form_create.yml> in your editor and update it 
281 to match:
282
283     ---
284     # indicator is the field that is used to test for form submission
285     indicator: submit
286     # Start listing the form elements
287     elements:
288         # The first element will be a text field for the title
289         - type: Text
290           name: title
291           label: Title
292           # This is an optional 'mouse over' title pop-up
293           attributes:
294             title: Enter a book title here
295           # Add constraints for the field
296           constraints:
297             # The user cannot leave this field blank
298             - Required
299             # Force the length to be between 2 and 30 chars
300             - type: Length
301               min: 2
302               max: 30
303               # Override the default of 'Invalid input'
304               message: Length must be between 2 and 30 characters
305         - type: Text
306           name: rating
307           label: Rating
308           attributes:
309             title: Enter a rating between 1 and 5 here
310           constraints:
311             - Required
312             # Make sure it's a number
313             - Integer
314         # The submit button
315         - type: Submit
316           name: submit
317           value: Submit
318     # Globally ensure that each field only specified one value
319     constraints:
320         - SingleValue
321
322 ...
323
324 =head1 AUTHOR
325
326 Kennedy Clark, C<hkclark@gmail.com>
327
328 Please report any errors, issues or suggestions to the author.  The
329 most recent version of the Catalyst Tutorial can be found at
330 L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
331
332 Copyright 2006, Kennedy Clark, under Creative Commons License
333 (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
334