Commit | Line | Data |
b80f58e5 |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Tutorial::AdvancedCRUD::FormFu - Catalyst Tutorial - Part 9: Advanced CRUD - FormFu |
4 | |
5 | |
c010ae0d |
6 | NOTE: This part of the tutorial is in progress and will be ready soon. |
7 | |
b80f58e5 |
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 | |
d682d02d |
50 | B<Advanced CRUD::FormFu> |
b80f58e5 |
51 | |
52 | =item 10 |
53 | |
54 | L<Appendices|Catalyst::Manual::Tutorial::Appendices> |
55 | |
56 | =back |
57 | |
58 | |
59 | =head1 DESCRIPTION |
60 | |
cca5cd98 |
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 | |
d682d02d |
115 | =head2 formfu_create |
cca5cd98 |
116 | |
59d6a035 |
117 | Use HTML::FormFu to create a new book |
cca5cd98 |
118 | |
119 | =cut |
120 | |
d682d02d |
121 | sub formfu_create :Local :FormConfig { |
cca5cd98 |
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; |
9cb64a37 |
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 | |
cca5cd98 |
154 | # Set the template |
d682d02d |
155 | $c->stash->{template} = 'books/formfu_create.tt2'; |
cca5cd98 |
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 | |
d682d02d |
167 | Then create the file C<root/forms/books/formfu_create.yml> and enter the |
cca5cd98 |
168 | following text: |
169 | |
170 | --- |
9cb64a37 |
171 | # indicator is the field that is used to test for form submission |
cca5cd98 |
172 | indicator: submit |
9cb64a37 |
173 | # Start listing the form elements |
cca5cd98 |
174 | elements: |
9cb64a37 |
175 | # The first element will be a text field for the title |
cca5cd98 |
176 | - type: Text |
177 | name: title |
178 | label: Title |
9cb64a37 |
179 | # This is an optional 'mouse over' title pop-up |
cca5cd98 |
180 | attributes: |
181 | title: Enter a book title here |
d682d02d |
182 | |
183 | # Another text field for the numeric rating |
cca5cd98 |
184 | - type: Text |
185 | name: rating |
186 | label: Rating |
187 | attributes: |
188 | title: Enter a rating between 1 and 5 here |
d682d02d |
189 | |
190 | # Add a drop-down list for the author selection. Note that we will |
191 | # dynamically fill in all the authors from the controller but we |
192 | # could manually set items in the drop-list by adding this YAML code: |
193 | # options: |
194 | # - [ '1', 'Bastien' ] |
195 | # - [ '2', 'Nasseh' ] |
196 | - type: Select |
197 | name: authors |
198 | label: Author |
199 | |
9cb64a37 |
200 | # The submit button |
cca5cd98 |
201 | - type: Submit |
202 | name: submit |
203 | value: Submit |
204 | |
0171092f |
205 | B<NOTE:> Copying and pasting YAML from perl documentation is sometimes |
206 | tricky. See the L<Copy-Paste versions of the YAML Config> section of |
207 | this document for a foolproof procedure. |
208 | |
cca5cd98 |
209 | |
210 | =head2 Update the CSS |
211 | |
212 | Edit C<root/src/ttsite.css> and add the following lines to the bottom of |
213 | the file: |
214 | |
d682d02d |
215 | input { |
cca5cd98 |
216 | display: block; |
217 | } |
d682d02d |
218 | select { |
cca5cd98 |
219 | display: block; |
220 | } |
d682d02d |
221 | .submit { |
222 | padding-top: .5em; |
223 | display: block; |
cca5cd98 |
224 | } |
225 | |
d682d02d |
226 | These changes will display form elements vertically. Note that the |
227 | existing definition of the C<.error> class is pulling the color scheme |
228 | settings from the C<root/lib/config/col> file that was created by the |
229 | TTSite helper. This allows control over the CSS color settings from a |
230 | single location. |
cca5cd98 |
231 | |
232 | |
233 | =head2 Create a Template Page To Display The Form |
234 | |
d682d02d |
235 | Open C<root/src/books/formfu_create.tt2> in your editor and enter the following: |
cca5cd98 |
236 | |
237 | [% META title = 'Create/Update Book' %] |
238 | |
239 | [%# Render the HTML::FormFu Form %] |
240 | [% form %] |
241 | |
242 | <p><a href="[% Catalyst.uri_for('list') %]">Return to book list</a></p> |
243 | |
244 | |
245 | =head2 Add Links for Create and Update via C<HTML::FormFu> |
246 | |
247 | Open C<root/src/books/list.tt2> in your editor and add the following to |
248 | the bottom of the existing file: |
249 | |
250 | <p> |
251 | HTML::FormFu: |
d682d02d |
252 | <a href="[% Catalyst.uri_for('formfu_create') %]">Create</a> |
cca5cd98 |
253 | </p> |
254 | |
d682d02d |
255 | This adds a new link to the bottom of the book list page that we can |
256 | use to easily launch our HTML::FormFu-based form. |
257 | |
cca5cd98 |
258 | |
d682d02d |
259 | =head2 Test The <HTML::FormFu> Create Form |
cca5cd98 |
260 | |
261 | Press C<Ctrl-C> to kill the previous server instance (if it's still |
262 | running) and restart it: |
263 | |
264 | $ script/myapp_server.pl |
265 | |
0909d46f |
266 | Login as C<test01> (password: mypass). Once at the Book List page, |
267 | click the new HTML::FormFu "Create" link at the bottom to display the |
268 | form. Fill in the following values: Title = "Internetworking with |
269 | TCP/IP Vol. II", Rating = "4", and Author = "Comer". Click Submit, |
270 | and you will be returned to the Book List page with a "Book created" |
271 | status message displayed. |
d682d02d |
272 | |
273 | Also note that this implementation allows you to can create books with |
274 | bogus information. Although we have constrained the authors with the |
59d6a035 |
275 | drop-down list (note that this isn't bulletproof because we still have |
276 | not prevented a user from "hacking" the form to specify other values), |
277 | there are no restrictions on items such as the length of the title (for |
278 | example, you can create a one-letter title) and value for the rating |
279 | (you can use any number you want, and even non-numeric values with |
280 | SQLite). The next section will address this concern. |
cca5cd98 |
281 | |
282 | B<Note:> Depending on the database you are using and how you established |
283 | the columns in your tables, the database could obviously provide various |
284 | levels of "type enforcement" on your data. The key point being made in |
285 | the previous paragraph is that the I<web application> itself is not |
286 | performing any validation. |
287 | |
288 | |
289 | =head1 C<HTML::FormFu> VALIDATION AND FILTERING |
290 | |
d682d02d |
291 | Although the use of L<HTML::FormFu|HTML::FormFu> in the previous section |
292 | did provide an automated mechanism to build the form, the real power of |
293 | this module stems from functionality that can automatically validate and |
294 | filter the user input. Validation uses constraints to be sure that |
295 | users input appropriate data (for example, that the email field of a |
296 | form contains a valid email address). Filtering can also be used to |
297 | remove extraneous whitespace from fields or to escape meta-characters in |
298 | user input. |
cca5cd98 |
299 | |
cca5cd98 |
300 | |
d682d02d |
301 | =head2 Add Constraints |
cca5cd98 |
302 | |
d682d02d |
303 | Open C<root/forms/books/formfu_create.yml> in your editor and update it |
cca5cd98 |
304 | to match: |
305 | |
306 | --- |
9cb64a37 |
307 | # indicator is the field that is used to test for form submission |
cca5cd98 |
308 | indicator: submit |
9cb64a37 |
309 | # Start listing the form elements |
cca5cd98 |
310 | elements: |
9cb64a37 |
311 | # The first element will be a text field for the title |
cca5cd98 |
312 | - type: Text |
313 | name: title |
314 | label: Title |
9cb64a37 |
315 | # This is an optional 'mouse over' title pop-up |
cca5cd98 |
316 | attributes: |
317 | title: Enter a book title here |
d682d02d |
318 | # Use Filter to clean up the input data |
319 | filter: |
320 | # Remove whitespace at both ends |
321 | - TrimEdges |
322 | # Escape HTML characters for safety |
323 | - HTMLEscape |
9cb64a37 |
324 | # Add constraints for the field |
cca5cd98 |
325 | constraints: |
9cb64a37 |
326 | # The user cannot leave this field blank |
59d6a035 |
327 | - SingleValue |
328 | # Force the length to be between 5 and 40 chars |
cca5cd98 |
329 | - type: Length |
d682d02d |
330 | min: 5 |
59d6a035 |
331 | max: 40 |
9cb64a37 |
332 | # Override the default of 'Invalid input' |
59d6a035 |
333 | message: Length must be between 5 and 40 characters |
d682d02d |
334 | |
335 | # Another text field for the numeric rating |
cca5cd98 |
336 | - type: Text |
337 | name: rating |
338 | label: Rating |
339 | attributes: |
340 | title: Enter a rating between 1 and 5 here |
d682d02d |
341 | # Use Filter to clean up the input data |
342 | filter: |
343 | # Remove whitespace at both ends |
344 | - TrimEdges |
345 | # Remove everything except digits |
346 | - NonNumeric |
347 | # Add constraints to the field |
cca5cd98 |
348 | constraints: |
59d6a035 |
349 | - SingleValue |
9cb64a37 |
350 | # Make sure it's a number |
cca5cd98 |
351 | - Integer |
d682d02d |
352 | |
353 | # Add a select list for the author selection. Note that we will |
354 | # dynamically fill in all the authors from the controller but we |
355 | # could manually set items in the select by adding this YAML code: |
356 | # options: |
357 | # - [ '1', 'Bastien' ] |
358 | # - [ '2', 'Nasseh' ] |
359 | - type: Select |
360 | name: authors |
361 | label: Author |
362 | # Convert the drop-down to a multi-select list |
363 | multiple: 1 |
364 | # Display 3 entries (user can scroll to see others) |
365 | size: 3 |
366 | # One could argue we don't need to do filters or constraints for |
367 | # a select list, but it's smart to do validation and sanity |
368 | # checks on this data in case a user "hacks" the input |
369 | # Use Filter to clean up the input data |
370 | filter: |
371 | # Remove whitespace at both ends |
372 | - TrimEdges |
373 | # Escape HTML characters for safety |
374 | - HTMLEscape |
375 | # Add constraints to the field |
376 | constraints: |
d682d02d |
377 | # Make sure it's a number |
378 | - Integer |
379 | |
9cb64a37 |
380 | # The submit button |
cca5cd98 |
381 | - type: Submit |
382 | name: submit |
383 | value: Submit |
d682d02d |
384 | |
9cb64a37 |
385 | # Globally ensure that each field only specified one value |
cca5cd98 |
386 | constraints: |
59d6a035 |
387 | # The user cannot leave any fields blank |
388 | - Required |
cca5cd98 |
389 | |
0171092f |
390 | B<NOTE:> Copying and pasting YAML from perl documentation is sometimes |
391 | tricky. See the L<Copy-Paste versions of the YAML Config> section of |
392 | this document for a foolproof procedure. |
393 | |
d682d02d |
394 | The main changes are: |
395 | |
396 | =over 4 |
397 | |
398 | =item * |
399 | |
400 | The C<Select> element for C<authors> is changed from a single-select |
401 | drop-down to a multi-select list by adding configuration for the |
402 | C<multiple> and C<size> options in C<formfu_create.yml>. |
403 | |
404 | =item * |
405 | |
406 | Constraints are added to provide validation of the user input. See |
407 | L<HTML::FormFu::Constraint|HTML::FormFu::Constraint> for other |
408 | constraints that are available. |
409 | |
410 | =item * |
411 | |
412 | A variety of filters are run on every field to remove and escape |
413 | unwanted input. See L<HTML::FormFu::Filter|HTML::FormFu::Filter> |
414 | for more filter options. |
415 | |
416 | =back |
417 | |
418 | |
419 | =head2 Try Out the Updated Form |
420 | |
421 | Press C<Ctrl-C> to kill the previous server instance (if it's still |
422 | running) and restart it: |
423 | |
424 | $ script/myapp_server.pl |
425 | |
59d6a035 |
426 | Make sure you are still logged in as C<test01> and try adding a book |
427 | with various errors: title less than 5 characters, non-numeric rating, a |
428 | rating of 0 or 6, etc. Also try selecting one, two, and zero authors. |
429 | When you click Submit, the HTML::FormFu C<constraint> items will |
430 | validate the logic and insert feedback as appropriate. Try adding blank |
431 | spaces at the front or the back of the title and note that it will be |
432 | removed. |
433 | |
434 | |
435 | =head1 CREATE AND UPDATE/EDIT ACTION |
436 | |
437 | Let's expand the work done above to add an edit action. First, open |
438 | C<lib/MyApp/Controller/Books.pm> and add the following method to the |
439 | bottom: |
440 | |
441 | =head2 formfu_edit |
442 | |
443 | Use HTML::FormFu to update an existing book |
444 | |
445 | =cut |
446 | |
447 | sub formfu_edit :Local :FormConfig('books/formfu_create.yml') { |
448 | my ($self, $c, $id) = @_; |
449 | |
450 | # Get the specified book |
451 | my $book = $c->model('DB::Books')->find($id); |
452 | |
453 | # Make sure we were able to get a book |
454 | unless ($book) { |
455 | $c->flash->{error_msg} = "Invalid book -- Cannot edit"; |
456 | $c->response->redirect($c->uri_for('list')); |
457 | $c->detach; |
458 | } |
459 | |
460 | # Get the form that the :FormConfig attribute saved in the stash |
461 | my $form = $c->stash->{form}; |
462 | |
463 | # Check if the form as been submitted (vs. displaying the initial |
464 | # form) and if the data based validation. "submitted_and_valid" |
465 | # is shorthand for "$form->submitted && !$form->has_errors" |
466 | if ($form->submitted_and_valid) { |
467 | # Save the form data for the book |
468 | $form->save_to_model($book); |
469 | # Set a status message for the user |
470 | $c->flash->{status_msg} = 'Book edited'; |
471 | # Return to the books list |
472 | $c->response->redirect($c->uri_for('list')); |
473 | $c->detach; |
474 | } else { |
475 | # Get the authors from the DB |
476 | my @authorObjs = $c->model("DB::Authors")->all(); |
477 | # Create an array of arrayrefs where each arrayref is an author |
478 | my @authors; |
479 | foreach (sort {$a->last_name cmp $b->last_name} @authorObjs) { |
480 | push(@authors, [$_->id, $_->last_name]); |
481 | } |
482 | # Get the select added by the config file |
483 | my $select = $form->get_element({type => 'Select'}); |
484 | # Add the authors to it |
485 | $select->options(\@authors); |
486 | # Populate the form with existing values from DB |
487 | $form->defaults_from_model($book); |
488 | } |
489 | |
490 | # Set the template |
491 | $c->stash->{template} = 'books/formfu_create.tt2'; |
492 | } |
493 | |
494 | Most of this code should look familiar to what we used in the |
495 | C<formfu_create> method (in fact, we should probably centralize some of |
496 | the common code in separate methods). The main differences are: |
497 | |
498 | =over 4 |
499 | |
500 | =item * |
501 | |
502 | We accept C<$id> as an argument via the URL. |
503 | |
504 | =item * |
505 | |
506 | We use C<$id> to look up the existing book from the database. |
507 | |
508 | =item * |
509 | |
510 | We make sure the C<$id> and book lookup returned a valid book. If not, |
511 | we set the error message and return to the book list. |
512 | |
513 | =item * |
514 | |
515 | If the form has been submitted and passes validation, we skip creating a |
516 | new book and just use C<$form-E<gt>save_to_model> to update the existing |
517 | book. |
518 | |
519 | =item * |
520 | |
521 | If the form is being displayed for the first time (or has failed |
522 | validation and it being redisplayed), we use |
523 | C<$form-E<gt>default_from_model> to populate the form with data from the |
524 | database. |
525 | |
526 | =back |
527 | |
528 | Then, edit C<root/src/books/list.tt2> and add a new link below the |
529 | existing "Delete" link that allows us to edit/update each existing book. |
530 | The last E<lt>tdE<gt> cell in the book list table should look like the |
531 | following: |
532 | |
533 | <td> |
534 | [% # Add a link to delete a book %] |
535 | <a href="[% Catalyst.uri_for('delete', book.id) %]">Delete</a> |
536 | [% # Add a link to edit a book %] |
537 | <a href="[% Catalyst.uri_for('formfu_edit', book.id) %]">Edit</a> |
538 | </td> |
539 | |
540 | |
541 | =head2 Try Out the Edit/Update Feature |
542 | |
543 | Press C<Ctrl-C> to kill the previous server instance (if it's still |
544 | running) and restart it: |
545 | |
546 | $ script/myapp_server.pl |
547 | |
548 | Make sure you are still logged in as C<test01> and go to the |
549 | L<http://localhost:3000/books/list> URL in your browser. Click the |
550 | "Edit" link next to "Internetworking with TCP/IP Vol. II", change the |
551 | rating to a 3, the "II" at end of the title to the number "2", add |
552 | Stevens as a co-author (control-click), and click Submit. You will then |
553 | be returned to the book list with a "Book edited" message at the top in |
554 | green. Experiment with other edits to various books. |
d682d02d |
555 | |
cca5cd98 |
556 | |
0171092f |
557 | =head2 Copy-Paste versions of the YAML Config. |
558 | |
559 | YAML, the config format used in formfu depends on whitespace and can |
560 | behave strangely in perl documentation because POD is also whitespace |
561 | dependent. If you copy and paste the YAML below into the file |
562 | C<root/forms/books/formfu_create.yml> and then run the following perl |
563 | oneliner, you're pretty much guaranteed to get valid YAML: |
564 | |
565 | $ perl -p -i -e 's/\s+\|//g' root/forms/books/formfu_create.yml |
566 | |
567 | =head2 YAML for the first half of the tutorial: |
568 | |
569 | |--- |
570 | |# indicator is the field that is used to test for form submission |
571 | |indicator: submit |
572 | |# Start listing the form elements |
573 | |elements: |
574 | | # The first element will be a text field for the title |
575 | | - type: Text |
576 | | name: title |
577 | | label: Title |
578 | | # This is an optional 'mouse over' title pop-up |
579 | | attributes: |
580 | | title: Enter a book title here |
581 | | |
582 | | # Another text field for the numeric rating |
583 | | - type: Text |
584 | | name: rating |
585 | | label: Rating |
586 | | attributes: |
587 | | title: Enter a rating between 1 and 5 here |
588 | | |
589 | | # Add a drop-down list for the author selection. Note that we will |
590 | | # dynamically fill in all the authors from the controller but we |
591 | | # could manually set items in the drop-list by adding this YAML code: |
592 | | # options: |
593 | | # - [ '1', 'Bastien' ] |
594 | | # - [ '2', 'Nasseh' ] |
595 | | - type: Select |
596 | | name: authors |
597 | | label: Author |
598 | | |
599 | | # The submit button |
600 | | - type: Submit |
601 | | name: submit |
602 | | value: Submit |
603 | |
604 | |
605 | =head2 YAML for the second part of the tutorial |
606 | |
607 | |--- |
608 | |# indicator is the field that is used to test for form submission |
609 | |indicator: submit |
610 | |# Start listing the form elements |
611 | |elements: |
612 | | # The first element will be a text field for the title |
613 | | - type: Text |
614 | | name: title |
615 | | label: Title |
616 | | # This is an optional 'mouse over' title pop-up |
617 | | attributes: |
618 | | title: Enter a book title here |
619 | | # Use Filter to clean up the input data |
620 | | filter: |
621 | | # Remove whitespace at both ends |
622 | | - TrimEdges |
623 | | # Escape HTML characters for safety |
624 | | - HTMLEscape |
625 | | # Add constraints for the field |
626 | | constraints: |
627 | | # The user cannot leave this field blank |
628 | | - SingleValue |
629 | | # Force the length to be between 5 and 40 chars |
630 | | - type: Length |
631 | | min: 5 |
632 | | max: 40 |
633 | | # Override the default of 'Invalid input' |
634 | | message: Length must be between 5 and 40 characters |
635 | | |
636 | | # Another text field for the numeric rating |
637 | | - type: Text |
638 | | name: rating |
639 | | label: Rating |
640 | | attributes: |
641 | | title: Enter a rating between 1 and 5 here |
642 | | # Use Filter to clean up the input data |
643 | | filter: |
644 | | # Remove whitespace at both ends |
645 | | - TrimEdges |
646 | | # Remove everything except digits |
647 | | - NonNumeric |
648 | | # Add constraints to the field |
649 | | constraints: |
650 | | - SingleValue |
651 | | # Make sure it's a number |
652 | | - Integer |
653 | | |
654 | | # Add a select list for the author selection. Note that we will |
655 | | # dynamically fill in all the authors from the controller but we |
656 | | # could manually set items in the select by adding this YAML code: |
657 | | # options: |
658 | | # - [ '1', 'Bastien' ] |
659 | | # - [ '2', 'Nasseh' ] |
660 | | - type: Select |
661 | | name: authors |
662 | | label: Author |
663 | | # Convert the drop-down to a multi-select list |
664 | | multiple: 1 |
665 | | # Display 3 entries (user can scroll to see others) |
666 | | size: 3 |
667 | | # One could argue we don't need to do filters or constraints for |
668 | | # a select list, but it's smart to do validation and sanity |
669 | | # checks on this data in case a user "hacks" the input |
670 | | # Use Filter to clean up the input data |
671 | | filter: |
672 | | # Remove whitespace at both ends |
673 | | - TrimEdges |
674 | | # Escape HTML characters for safety |
675 | | - HTMLEscape |
676 | | # Add constraints to the field |
677 | | constraints: |
678 | | # Make sure it's a number |
679 | | - Integer |
680 | | |
681 | | # The submit button |
682 | | - type: Submit |
683 | | name: submit |
684 | | value: Submit |
685 | | |
686 | |# Globally ensure that each field only specified one value |
687 | |constraints: |
688 | | # The user cannot leave any fields blank |
689 | | - Required |
690 | |
cca5cd98 |
691 | =head1 AUTHOR |
692 | |
693 | Kennedy Clark, C<hkclark@gmail.com> |
694 | |
695 | Please report any errors, issues or suggestions to the author. The |
696 | most recent version of the Catalyst Tutorial can be found at |
697 | L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>. |
698 | |
d682d02d |
699 | Copyright 20066-2008, Kennedy Clark, under Creative Commons License |
cca5cd98 |
700 | (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>). |
0909d46f |
701 | |