=head1 DESCRIPTION
-This portion of the tutorial explores L<HTML::FormFu|HTML::FormFu> and
-how it can be used to manage forms, perform validation of form input,
-as well as save and restore data to/from the database. This was written
-using HTML::FormFu version 0.05001.
+This portion of the tutorial explores L<HTML::FormFu> and how it can be
+used to manage forms, perform validation of form input, as well as save
+and restore data to/from the database.
-See
-L<Catalyst::Manual::Tutorial::09_AdvancedCRUD|Catalyst::Manual::Tutorial::09_AdvancedCRUD>
-for additional form management options other than
-L<HTML::FormFu|HTML::FormFu>.
+See L<Catalyst::Manual::Tutorial::09_AdvancedCRUD> for additional form
+management options other than L<HTML::FormFu>.
=head1 HTML::FormFu FORM CREATION
-This section looks at how L<HTML::FormFu|HTML::FormFu> can be used to
-add additional functionality to the manually created form from Chapter 4.
+This section looks at how L<HTML::FormFu> can be used to add additional
+functionality to the manually created form from
+L<Chapter 4|Catalyst::Manual::Tutorial::04_BasicCRUD>.
=head2 Inherit From Catalyst::Controller::HTML::FormFu
First, change your C<lib/MyApp/Controller/Books.pm> to inherit from
-L<Catalyst::Controller::HTML::FormFu|Catalyst::Controller::HTML::FormFu>
-by changing the C<extends> line from the default of:
+L<Catalyst::Controller::HTML::FormFu> by changing the C<extends> line
+from the default of:
BEGIN {extends 'Catalyst::Controller'; }
BEGIN {extends 'Catalyst::Controller::HTML::FormFu'; }
+Don't forget to add:
+
+ requires 'HTML::FormFu';
+ requires 'Catalyst::Controller::HTML::FormFu';
+ requires 'requires 'HTML::FormFu::Model::DBIC';';
+
+to your C<Makefile.PL>.
+
=head2 Add Action to Display and Save the Form
# Get the form that the :FormConfig attribute saved in the stash
my $form = $c->stash->{form};
-
+
# Check if the form has been submitted (vs. displaying the initial
# form) and if the data passed validation. "submitted_and_valid"
# is shorthand for "$form->submitted && !$form->has_errors"
my $book = $c->model('DB::Book')->new_result({});
# Save the form data for the book
$form->model->update($book);
- # Set a status message for the user
- $c->flash->{status_msg} = 'Book created';
- # Return to the books list
- $c->response->redirect($c->uri_for($self->action_for('list')));
+ # Set a status message for the user & return to books list
+ $c->response->redirect($c->uri_for($self->action_for('list'),
+ {mid => $c->set_status_msg("Book created")}));
$c->detach;
} else {
# Get the authors from the DB
# Add the authors to it
$select->options(\@authors);
}
-
+
# Set the template
- $c->stash->{template} = 'books/formfu_create.tt2';
+ $c->stash(template => 'books/formfu_create.tt2');
}
=head2 Create a Form Config File
Although C<HTML::FormFu> supports any configuration file handled by
-L<Config::Any|Config::Any>, most people tend to use YAML. First
-create a directory to hold your form configuration files:
+L<Config::Any>, most people tend to use YAML. First create a directory
+to hold your form configuration files:
- mkdir -p root/forms/books
+ $ mkdir -p root/forms/books
-Then create the file C<root/forms/books/formfu_create.yml> and enter the
+Then create the file C<root/forms/books/formfu_create.yml> and enter the
following text:
---
name: submit
value: Submit
-B<NOTE:> Copying and pasting YAML from perl documentation is sometimes
+B<NOTE:> Copying and pasting YAML from Perl documentation is sometimes
tricky. See the L<Config::General Config for this tutorial> section of
this document for a more foolproof config format.
=head2 Update the CSS
-Edit C<root/static/css/main.css> and add the following lines to the bottom of
-the file:
+Edit C<root/static/css/main.css> and add the following lines to the
+bottom of the file:
...
input {
display: block;
}
-These changes will display form elements vertically. Note that the
-existing definition of the C<.error> class is pulling the color scheme
-settings from the C<root/lib/config/col> file that was created by the
-TTSite helper. This allows control over the CSS color settings from a
-single location.
+These changes will display form elements vertically.
=head2 Create a Template Page To Display The Form
-Open C<root/src/books/formfu_create.tt2> in your editor and enter the following:
+Open C<root/src/books/formfu_create.tt2> in your editor and enter the
+following:
[% META title = 'Create/Update Book' %]
[%# Render the HTML::FormFu Form %]
[% form %]
- <p><a href="[% c.uri_for(c.controller.action_for('list')) %]">Return to book list</a></p>
+ <p><a href="[% c.uri_for(c.controller.action_for('list'))
+ %]">Return to book list</a></p>
=head2 Add Links for Create and Update via C<HTML::FormFu>
<a href="[% c.uri_for(c.controller.action_for('formfu_create')) %]">Create</a>
</p>
-This adds a new link to the bottom of the book list page that we can
-use to easily launch our HTML::FormFu-based form.
+This adds a new link to the bottom of the book list page that we can use
+to easily launch our HTML::FormFu-based form.
=head2 Test The HTML::FormFu Create Form
-Press C<Ctrl-C> to kill the previous server instance (if it's still
-running) and restart it:
+Make sure the server is running with the "-r" restart option:
- $ script/myapp_server.pl
+ $ script/myapp_server.pl -r
Login as C<test01> (password: mypass). Once at the Book List page,
click the new HTML::FormFu "Create" link at the bottom to display the
form. Fill in the following values:
-Title: Internetworking with TCP/IP Vol. II
-Rating: 4
-Author: Comer
-
-Click the Submit button, and you will be returned to the Book List page
+ Title: Internetworking with TCP/IP Vol. II
+ Rating: 4
+ Author: Comer
+
+Click the "Submit" button, and you will be returned to the Book List page
with a "Book created" status message displayed.
Also note that this implementation allows you to create books with any
-bogus information. Although we have constrained the authors with the
-drop-down list (note that this isn't bulletproof because we still have
-not prevented a user from "hacking" the form to specify other values),
-there are no restrictions on items such as the length of the title (for
-example, you can create a one-letter title) and the value of the rating
-(you can use any number you want, and even non-numeric values with
+bogus information. Although we have constrained the authors with the
+drop-down list (note that this isn't bulletproof because we still have
+not prevented a user from "hacking" the form to specify other values),
+there are no restrictions on items such as the length of the title (for
+example, you can create a one-letter title) and the value of the rating
+(you can use any number you want, and even non-numeric values with
SQLite). The next section will address this concern.
B<Note:> Depending on the database you are using and how you established
=head1 HTML::FormFu VALIDATION AND FILTERING
-Although the use of L<HTML::FormFu|HTML::FormFu> in the previous section
-did provide an automated mechanism to build the form, the real power of
-this module stems from functionality that can automatically validate and
-filter the user input. Validation uses constraints to be sure that
-users input appropriate data (for example, that the email field of a
-form contains a valid email address). Filtering can also be used to
-remove extraneous whitespace from fields or to escape meta-characters in
-user input.
+Although the use of L<HTML::FormFu> in the previous section did provide
+an automated mechanism to build the form, the real power of this module
+stems from functionality that can automatically validate and filter the
+user input. Validation uses constraints to be sure that users input
+appropriate data (for example, that the email field of a form contains a
+valid email address). Filtering can also be used to remove extraneous
+whitespace from fields or to escape meta-characters in user input.
=head2 Add Constraints
-Open C<root/forms/books/formfu_create.yml> in your editor and update it
+Open C<root/forms/books/formfu_create.yml> in your editor and update it
to match:
---
# Global filters and constraints.
constraints:
- # The user cannot leave any fields blank
- - Required
- # If not all fields are required, move the Required constraint to the
- # fields that are
+ # The user cannot leave any fields blank
+ - Required
+ # If not all fields are required, move the Required constraint to the
+ # fields that are
filter:
- # Remove whitespace at both ends
- - TrimEdges
- # Escape HTML characters for safety
- - HTMLEscape
+ # Remove whitespace at both ends
+ - TrimEdges
+ # Escape HTML characters for safety
+ - HTMLEscape
-B<NOTE:> Copying and pasting YAML from perl documentation is sometimes
+B<NOTE:> Copying and pasting YAML from Perl documentation is sometimes
tricky. See the L<Config::General Config for this tutorial> section of
this document for a more foolproof config format.
=item *
The C<Select> element for C<authors> is changed from a single-select
-drop-down to a multi-select list by adding configuration for the
+drop-down to a multi-select list by adding configuration for the
C<multiple> and C<size> options in C<formfu_create.yml>.
=item *
Constraints are added to provide validation of the user input. See
-L<HTML::FormFu::Constraint|HTML::FormFu::Constraint> for other
-constraints that are available.
+L<HTML::FormFu::Constraint> for other constraints that are available.
=item *
-A variety of filters are run on every field to remove and escape
-unwanted input. See L<HTML::FormFu::Filter|HTML::FormFu::Filter>
-for more filter options.
+A variety of filters are run on every field to remove and escape
+unwanted input. See L<HTML::FormFu::Filter> for more filter options.
=back
=head2 Try Out the Updated Form
-Press C<Ctrl-C> to kill the previous server instance (if it's still
-running) and restart it:
-
- $ script/myapp_server.pl
-
-Make sure you are still logged in as C<test01> and try adding a book
-with various errors: title less than 5 characters, non-numeric rating, a
-rating of 0 or 6, etc. Also try selecting one, two, and zero authors.
-When you click Submit, the HTML::FormFu C<constraint> items will
-validate the logic and insert feedback as appropriate. Try adding blank
-spaces at the front or the back of the title and note that it will be
+Make sure you are still logged in as C<test01> and try adding a book
+with various errors: title less than 5 characters, non-numeric rating, a
+rating of 0 or 6, etc. Also try selecting one, two, and zero authors.
+When you click Submit, the HTML::FormFu C<constraint> items will
+validate the logic and insert feedback as appropriate. Try adding blank
+spaces at the front or the back of the title and note that it will be
removed.
+Note that you can update your FormFu YAML forms and the development
+server does not need to reload -- the form definition is read from
+the YAML file each time a controller action uses it.
+
=head1 CREATE AND UPDATE/EDIT ACTION
-Let's expand the work done above to add an edit action. First, open
-C<lib/MyApp/Controller/Books.pm> and add the following method to the
+Let's expand the work done above to add an edit action. First, open
+C<lib/MyApp/Controller/Books.pm> and add the following method to the
bottom:
=head2 formfu_edit
# Make sure we were able to get a book
unless ($book) {
- $c->flash->{error_msg} = "Invalid book -- Cannot edit";
- $c->response->redirect($c->uri_for($self->action_for('list')));
+ # Set an error message for the user & return to books list
+ $c->response->redirect($c->uri_for($self->action_for('list'),
+ {mid => $c->set_error_msg("Invalid book -- Cannot edit")}));
$c->detach;
}
# Save the form data for the book
$form->model->update($book);
# Set a status message for the user
- $c->flash->{status_msg} = 'Book edited';
- # Return to the books list
- $c->response->redirect($c->uri_for($self->action_for('list')));
+ # Set a status message for the user & return to books list
+ $c->response->redirect($c->uri_for($self->action_for('list'),
+ {mid => $c->set_status_msg("Book edited")}));
$c->detach;
} else {
# Get the authors from the DB
}
# Set the template
- $c->stash->{template} = 'books/formfu_create.tt2';
+ $c->stash(template => 'books/formfu_create.tt2');
}
-Most of this code should look familiar to what we used in the
-C<formfu_create> method (in fact, we should probably centralize some of
+Most of this code should look familiar to what we used in the
+C<formfu_create> method (in fact, we should probably centralize some of
the common code in separate methods). The main differences are:
=over 4
=item *
-We have to manually specify the name of the FormFu .yml file as an
-argument to C<:FormConfig> because the name can no longer be
+We have to manually specify the name of the FormFu .yml file as an
+argument to C<:FormConfig> because the name can no longer be
automatically deduced from the name of our action/method (by default,
FormFu would look for a file named C<books/formfu_edit.yml>).
=item *
-We load the book object from the stash (found using the $id passed to
+We load the book object from the stash (found using the $id passed to
the Chained object method)
=item *
=item *
-We make sure the book lookup returned a valid book. If not, we set
-the error message and return to the book list.
+We make sure the book lookup returned a valid book. If not, we set the
+error message and return to the book list.
=item *
-If the form has been submitted and passes validation, we skip creating a
-new book and just use C<$form-E<gt>model-E<gt>update> to update the existing
-book.
+If the form has been submitted and passes validation, we skip creating a
+new book and just use C<$form-E<gt>model-E<gt>update> to update the
+existing book.
=item *
-If the form is being displayed for the first time (or has failed
+If the form is being displayed for the first time (or has failed
validation and it being redisplayed), we use
- C<$form-E<gt>model-E<gt>default_values> to populate the form with data from the
-database.
+C<$form-E<gt>model-E<gt>default_values> to populate the form with data
+from the database.
=back
-Then, edit C<root/src/books/list.tt2> and add a new link below the
-existing "Delete" link that allows us to edit/update each existing book.
-The last E<lt>tdE<gt> cell in the book list table should look like the
+Then, edit C<root/src/books/list.tt2> and add a new link below the
+existing "Delete" link that allows us to edit/update each existing book.
+The last E<lt>tdE<gt> cell in the book list table should look like the
following:
...
<td>
[% # Add a link to delete a book %]
- <a href="[% c.uri_for(c.controller.action_for('delete'), [book.id]) %]">Delete</a>
+ <a href="[%
+ c.uri_for(c.controller.action_for('delete'), [book.id]) %]">Delete</a>
[% # Add a link to edit a book %]
- <a href="[% c.uri_for(c.controller.action_for('formfu_edit'), [book.id]) %]">Edit</a>
+ <a href="[%
+ c.uri_for(c.controller.action_for('formfu_edit'), [book.id]) %]">Edit</a>
</td>
...
-B<Note:> Only add two lines (the "Add a link to edit a book" comment
-and the href for C<formfu_edit>). Make sure you add it below the
-existing C<delete> link.
+B<Note:> Only add three lines (the "Add a link to edit a book" comment and
+the href for C<formfu_edit>). Make sure you add it below the existing
+C<delete> link.
=head2 Try Out the Edit/Update Feature
-Press C<Ctrl-C> to kill the previous server instance (if it's still
-running) and restart it:
-
- $ script/myapp_server.pl
-
-Make sure you are still logged in as C<test01> and go to the
-L<http://localhost:3000/books/list> URL in your browser. Click the
-"Edit" link next to "Internetworking with TCP/IP Vol. II", change the
-rating to a 3, the "II" at end of the title to the number "2", add
-Stevens as a co-author (control-click), and click Submit. You will then
-be returned to the book list with a "Book edited" message at the top in
+Make sure you are still logged in as C<test01> and go to the
+L<http://localhost:3000/books/list> URL in your browser. Click the
+"Edit" link next to "Internetworking with TCP/IP Vol. II", change the
+rating to a 3, the "II" at end of the title to the number "2", add
+Stevens as a co-author (control-click), and click Submit. You will then
+be returned to the book list with a "Book edited" message at the top in
green. Experiment with other edits to various books.
real reason you worked through this Tutorial in the first place.
-=head2 Config::General Config for this tutorial
+=head2 Config::General Config for this tutorial
If you are having difficulty with YAML config above, please save the
below into the file C<formfu_create.conf> and delete the
-C<formfu_create.yml> file. The below is in
-L<Config::General|Config::General> format which follows the syntax of
-Apache config files.
+C<formfu_create.yml> file. The below is in L<Config::General> format
+which follows the syntax of Apache config files.
constraints Required
<elements>
type Submit
</elements>
indicator submit
-
+
=head1 AUTHOR
Kennedy Clark, C<hkclark@gmail.com>
-Please report any errors, issues or suggestions to the author. The
-most recent version of the Catalyst Tutorial can be found at
+Feel free to contact the author for any errors or suggestions, but the
+best way to report issues is via the CPAN RT Bug system at
+<https://rt.cpan.org/Public/Dist/Display.html?Name=Catalyst-Manual>.
+
+The most recent version of the Catalyst Tutorial can be found at
L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.80/trunk/lib/Catalyst/Manual/Tutorial/>.
-Copyright 2006-2008, Kennedy Clark, under Creative Commons License
-(L<http://creativecommons.org/licenses/by-sa/3.0/us/>).
+Copyright 2006-2010, Kennedy Clark, under the
+Creative Commons Attribution Share-Alike License Version 3.0
+(L<http://creativecommons.org/licenses/by-sa/3.0/us/>).