3 Catalyst::Manual::Tutorial::AdvancedCRUD::FormFu - Catalyst Tutorial - Part 9: Advanced CRUD - FormFu
6 NOTE: This part of the tutorial is in progress and will be ready soon.
10 This is B<Part 9 of 10> for the Catalyst tutorial.
12 L<Tutorial Overview|Catalyst::Manual::Tutorial>
18 L<Introduction|Catalyst::Manual::Tutorial::Intro>
22 L<Catalyst Basics|Catalyst::Manual::Tutorial::CatalystBasics>
26 L<More Catalyst Basics|Catalyst::Manual::Tutorial::MoreCatalystBasics>
30 L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
34 L<Authentication|Catalyst::Manual::Tutorial::Authentication>
38 L<Authorization|Catalyst::Manual::Tutorial::Authorization>
42 L<Debugging|Catalyst::Manual::Tutorial::Debugging>
46 L<Testing|Catalyst::Manual::Tutorial::Testing>
50 B<Advanced CRUD::FormFu>
54 L<Appendices|Catalyst::Manual::Tutorial::Appendices>
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.
66 L<Catalyst::Manual::Tutorial::AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
67 for additional form management options other than
68 L<HTML::FormFu|HTML::FormFu>.
71 =head1 Install C<HTML::FormFu>
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>:
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
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>:
87 sudo cpan File::ShareDir Task::Weaken Config::Any HTML::FormFu \
88 Catalyst::Controller::HTML::FormFu
91 =head1 C<HTML::FormFu> FORM CREATION
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.
97 =head2 Inherit From C<Catalyst::Controller::HTML::FormFu>
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:
103 use base 'Catalyst::Controller';
105 to use the FormFu base controller class:
107 use base 'Catalyst::Controller::HTML::FormFu';
110 =head2 Add Action to Display and Save the Form
112 Open C<lib/MyApp/Controller/Books.pm> in your editor and add the
117 Build an HTML::FormFu form for book creation and updates
121 sub formfu_create :Local :FormConfig {
124 # Get the form that the :FormConfig attribute saved in the stash
125 my $form = $c->stash->{form};
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) {
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'));
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
145 foreach (sort {$a->last_name cmp $b->last_name} @authorObjs) {
146 push(@authors, [$_->id, $_->last_name]);
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);
155 $c->stash->{template} = 'books/formfu_create.tt2';
159 =head2 Create a Form Config File
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:
165 mkdir -p root/forms/books
167 Then create the file C<root/forms/books/formfu_create.yml> and enter the
171 # indicator is the field that is used to test for form submission
173 # Start listing the form elements
175 # The first element will be a text field for the title
179 # This is an optional 'mouse over' title pop-up
181 title: Enter a book title here
183 # Another text field for the numeric rating
188 title: Enter a rating between 1 and 5 here
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:
194 # - [ '1', 'Bastien' ]
195 # - [ '2', 'Nasseh' ]
206 =head2 Update the CSS
208 Edit C<root/src/ttsite.css> and add the following lines to the bottom of
222 These changes will display form elements vertically. Note that the
223 existing definition of the C<.error> class is pulling the color scheme
224 settings from the C<root/lib/config/col> file that was created by the
225 TTSite helper. This allows control over the CSS color settings from a
229 =head2 Create a Template Page To Display The Form
231 Open C<root/src/books/formfu_create.tt2> in your editor and enter the following:
233 [% META title = 'Create/Update Book' %]
235 [%# Render the HTML::FormFu Form %]
238 <p><a href="[% Catalyst.uri_for('list') %]">Return to book list</a></p>
241 =head2 Add Links for Create and Update via C<HTML::FormFu>
243 Open C<root/src/books/list.tt2> in your editor and add the following to
244 the bottom of the existing file:
248 <a href="[% Catalyst.uri_for('formfu_create') %]">Create</a>
251 This adds a new link to the bottom of the book list page that we can
252 use to easily launch our HTML::FormFu-based form.
255 =head2 Test The <HTML::FormFu> Create Form
257 Press C<Ctrl-C> to kill the previous server instance (if it's still
258 running) and restart it:
260 $ script/myapp_server.pl
262 Login as C<test01>. Once at the Book List page, click the new
263 HTML::FormFu "Create" link at the bottom to display the form. Fill in
264 the following values: Title = "Internetworking with TCP/IP Vol. II",
265 Rating = "4", and Author = "Comer". Click Submit, and you will be
266 returned to the Book List page with a "Book created" status message
269 Also note that this implementation allows you to can create books with
270 bogus information. Although we have constrained the authors with the
271 drop-down list (somewhat, we still have not prevented a user from
272 "hacking" the form to specify other values), there are no restrictions
273 on items such as the length of the title (for example, you can create a
274 one-letter title) and value for the rating (you can use any number you
275 want, and even non-numeric values with SQLite). The next section will
276 address this concern.
278 B<Note:> Depending on the database you are using and how you established
279 the columns in your tables, the database could obviously provide various
280 levels of "type enforcement" on your data. The key point being made in
281 the previous paragraph is that the I<web application> itself is not
282 performing any validation.
285 =head1 C<HTML::FormFu> VALIDATION AND FILTERING
287 Although the use of L<HTML::FormFu|HTML::FormFu> in the previous section
288 did provide an automated mechanism to build the form, the real power of
289 this module stems from functionality that can automatically validate and
290 filter the user input. Validation uses constraints to be sure that
291 users input appropriate data (for example, that the email field of a
292 form contains a valid email address). Filtering can also be used to
293 remove extraneous whitespace from fields or to escape meta-characters in
297 =head2 Add Constraints
299 Open C<root/forms/books/formfu_create.yml> in your editor and update it
303 # indicator is the field that is used to test for form submission
305 # Start listing the form elements
307 # The first element will be a text field for the title
311 # This is an optional 'mouse over' title pop-up
313 title: Enter a book title here
314 # Use Filter to clean up the input data
316 # Remove whitespace at both ends
318 # Escape HTML characters for safety
320 # Add constraints for the field
322 # The user cannot leave this field blank
324 # Force the length to be between 5 and 30 chars
328 # Override the default of 'Invalid input'
329 message: Length must be between 5 and 30 characters
331 # Another text field for the numeric rating
336 title: Enter a rating between 1 and 5 here
337 # Use Filter to clean up the input data
339 # Remove whitespace at both ends
341 # Remove everything except digits
343 # Add constraints to the field
346 # Make sure it's a number
349 # Add a select list for the author selection. Note that we will
350 # dynamically fill in all the authors from the controller but we
351 # could manually set items in the select by adding this YAML code:
353 # - [ '1', 'Bastien' ]
354 # - [ '2', 'Nasseh' ]
358 # Convert the drop-down to a multi-select list
360 # Display 3 entries (user can scroll to see others)
362 # One could argue we don't need to do filters or constraints for
363 # a select list, but it's smart to do validation and sanity
364 # checks on this data in case a user "hacks" the input
365 # Use Filter to clean up the input data
367 # Remove whitespace at both ends
369 # Escape HTML characters for safety
371 # Add constraints to the field
374 # Make sure it's a number
382 # Globally ensure that each field only specified one value
386 The main changes are:
392 The C<Select> element for C<authors> is changed from a single-select
393 drop-down to a multi-select list by adding configuration for the
394 C<multiple> and C<size> options in C<formfu_create.yml>.
398 Constraints are added to provide validation of the user input. See
399 L<HTML::FormFu::Constraint|HTML::FormFu::Constraint> for other
400 constraints that are available.
404 A variety of filters are run on every field to remove and escape
405 unwanted input. See L<HTML::FormFu::Filter|HTML::FormFu::Filter>
406 for more filter options.
411 =head2 Try Out the Updated Form
413 Press C<Ctrl-C> to kill the previous server instance (if it's still
414 running) and restart it:
416 $ script/myapp_server.pl
418 Now try adding a book with various errors: title less than 5 characters,
419 non-numeric rating, a rating of 0 or 6, etc. Also try selecting one,
420 two, and zero authors. When you click Submit, the HTML::FormFu
421 C<constraint> items will validate the logic and insert feedback as
422 appropriate. Try adding blank spaces at the front or the back of the
423 title and note that it will be removed.
428 Kennedy Clark, C<hkclark@gmail.com>
430 Please report any errors, issues or suggestions to the author. The
431 most recent version of the Catalyst Tutorial can be found at
432 L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
434 Copyright 20066-2008, Kennedy Clark, under Creative Commons License
435 (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).