X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FTutorial%2FAdvancedCRUD%2FFormFu.pod;h=4e6dba6814999f98c89b68fe7681bf3e397fb56b;hb=f279297ad42ed1dc1fc4e2289a4a1dc17acf91d7;hp=cb278195f677de6b4b88dbbb4266677e6de5aa77;hpb=d682d02dcc437ec810c6d45fbdce586cb6ae3c0e;p=catagits%2FCatalyst-Manual.git diff --git a/lib/Catalyst/Manual/Tutorial/AdvancedCRUD/FormFu.pod b/lib/Catalyst/Manual/Tutorial/AdvancedCRUD/FormFu.pod index cb27819..4e6dba6 100644 --- a/lib/Catalyst/Manual/Tutorial/AdvancedCRUD/FormFu.pod +++ b/lib/Catalyst/Manual/Tutorial/AdvancedCRUD/FormFu.pod @@ -1,5 +1,7 @@ =head1 NAME + + Catalyst::Manual::Tutorial::AdvancedCRUD::FormFu - Catalyst Tutorial - Part 9: Advanced CRUD - FormFu @@ -114,7 +116,7 @@ following method: =head2 formfu_create - Build an HTML::FormFu form for book creation and updates + Use HTML::FormFu to create a new book =cut @@ -124,8 +126,8 @@ following method: # Get the form that the :FormConfig attribute saved in the stash my $form = $c->stash->{form}; - # Check if the form as been submitted (vs. displaying the initial - # form) and if the data based validation. "submitted_and_valid" + # 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" if ($form->submitted_and_valid) { # Create a new book @@ -202,6 +204,10 @@ following text: name: submit value: Submit +B Copying and pasting YAML from perl documentation is sometimes +tricky. See the L section of +this document for a more foolproof config format. + =head2 Update the CSS @@ -235,7 +241,7 @@ Open C in your editor and enter the following: [%# Render the HTML::FormFu Form %] [% form %] -

Return to book list

+

Return to book list

=head2 Add Links for Create and Update via C @@ -245,7 +251,7 @@ the bottom of the existing file:

HTML::FormFu: - Create + Create

This adds a new link to the bottom of the book list page that we can @@ -259,21 +265,21 @@ running) and restart it: $ script/myapp_server.pl -Login as C. 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", and Author = "Comer". Click Submit, and you will be -returned to the Book List page with a "Book created" status message -displayed. +Login as C (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", and Author = "Comer". Click Submit, +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 can create books with bogus information. Although we have constrained the authors with the -drop-down list (somewhat, 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 value for the rating (you can use any number you -want, and even non-numeric values with SQLite). The next section will -address this concern. +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 value for the rating +(you can use any number you want, and even non-numeric values with +SQLite). The next section will address this concern. B Depending on the database you are using and how you established the columns in your tables, the database could obviously provide various @@ -311,23 +317,15 @@ to match: # This is an optional 'mouse over' title pop-up attributes: title: Enter a book title here - # Use Filter to clean up the input data - filter: - # Remove whitespace at both ends - - TrimEdges - # Escape HTML characters for safety - - HTMLEscape # Add constraints for the field constraints: - # The user cannot leave this field blank - - Required - # Force the length to be between 5 and 30 chars + # Force the length to be between 5 and 40 chars - type: Length min: 5 - max: 30 + max: 40 # Override the default of 'Invalid input' - message: Length must be between 5 and 30 characters - + message: Length must be between 5 and 40 characters + # Another text field for the numeric rating - type: Text name: rating @@ -336,8 +334,6 @@ to match: title: Enter a rating between 1 and 5 here # Use Filter to clean up the input data filter: - # Remove whitespace at both ends - - TrimEdges # Remove everything except digits - NonNumeric # Add constraints to the field @@ -345,6 +341,10 @@ to match: - Required # Make sure it's a number - Integer + message: "Digits only, please." + # Filters apply before constraints. + # If a user gives the rating "excellent", the NonNumeric filter would remove the entire string as it contains no digits. + # Remove the NonNumeric filter and let the Integer constraint handle the validation and error message. # Add a select list for the author selection. Note that we will # dynamically fill in all the authors from the controller but we @@ -362,15 +362,8 @@ to match: # One could argue we don't need to do filters or constraints for # a select list, but it's smart to do validation and sanity # checks on this data in case a user "hacks" the input - # Use Filter to clean up the input data - filter: - # Remove whitespace at both ends - - TrimEdges - # Escape HTML characters for safety - - HTMLEscape # Add constraints to the field constraints: - - Required # Make sure it's a number - Integer @@ -379,9 +372,20 @@ to match: name: submit value: Submit - # Globally ensure that each field only specified one value + # Global filters and constraints. constraints: - - SingleValue + # 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 + +B Copying and pasting YAML from perl documentation is sometimes +tricky. See the L section of +this document for a more foolproof config format. The main changes are: @@ -415,12 +419,190 @@ running) and restart it: $ script/myapp_server.pl -Now 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 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. +Make sure you are still logged in as C 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 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. + + +=head1 CREATE AND UPDATE/EDIT ACTION + +Let's expand the work done above to add an edit action. First, open +C and add the following method to the +bottom: + + =head2 formfu_edit + + Use HTML::FormFu to update an existing book + + =cut + + sub formfu_edit :Local :FormConfig('books/formfu_create.yml') { + my ($self, $c, $id) = @_; + + # Get the specified book + my $book = $c->model('DB::Books')->find($id); + + # 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('list')); + $c->detach; + } + + # 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" + if ($form->submitted_and_valid) { + # Save the form data for the book + $form->save_to_model($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('list')); + $c->detach; + } else { + # Get the authors from the DB + my @authorObjs = $c->model("DB::Authors")->all(); + # Create an array of arrayrefs where each arrayref is an author + my @authors; + foreach (sort {$a->last_name cmp $b->last_name} @authorObjs) { + push(@authors, [$_->id, $_->last_name]); + } + # Get the select added by the config file + my $select = $form->get_element({type => 'Select'}); + # Add the authors to it + $select->options(\@authors); + # Populate the form with existing values from DB + $form->defaults_from_model($book); + } + + # Set the template + $c->stash->{template} = 'books/formfu_create.tt2'; + } + +Most of this code should look familiar to what we used in the +C method (in fact, we should probably centralize some of +the common code in separate methods). The main differences are: + +=over 4 + +=item * + +We accept C<$id> as an argument via the URL. + +=item * + +We use C<$id> to look up the existing book from the database. + +=item * + +We make sure the C<$id> and 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-Esave_to_model> to update the existing +book. + +=item * + +If the form is being displayed for the first time (or has failed +validation and it being redisplayed), we use + C<$form-Edefault_from_model> to populate the form with data from the +database. + +=back + +Then, edit C and add a new link below the +existing "Delete" link that allows us to edit/update each existing book. +The last EtdE cell in the book list table should look like the +following: + + + [% # Add a link to delete a book %] + Delete + [% # Add a link to edit a book %] + Edit + + + +=head2 Try Out the Edit/Update Feature + +Press 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 and go to the +L 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. + + +=head2 Config::General Config for this tutorial + +If you are having difficulty with YAML config above, please save the +below into the file C and delete the +C file. The below is in +L format which follows the syntax of +Apache config files. + + constraints Required + + + min 5 + max 40 + type Length + message Length must be between 5 and 40 characters + + filter TrimEdges + filter HTMLEscape + name title + type Text + label Title + + title Enter a book title here + + + + constraints Integer + filter TrimEdges + filter NonNumeric + name rating + type Text + label Rating + + title Enter a rating between 1 and 5 here + + + + constraints Integer + filter TrimEdges + filter HTMLEscape + name authors + type Select + label Author + multiple 1 + size 3 + + + value Submit + name submit + type Submit + + indicator submit + =head1 AUTHOR @@ -433,4 +615,4 @@ L). - \ No newline at end of file +