.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "HTML::FormHandler::Manual::Tutorial 3pm" .TH HTML::FormHandler::Manual::Tutorial 3pm "2022-03-25" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" HTML::FormHandler::Manual::Tutorial \- how to use FormHandler with Catalyst .SH "VERSION" .IX Header "VERSION" version 0.40068 .SH "SYNOPSIS" .IX Header "SYNOPSIS" Manual Index .PP A tutorial for beginners to HTML::FormHandler .SH "Using HTML::FormHandler with Catalyst" .IX Header "Using HTML::FormHandler with Catalyst" This tutorial demonstrates how you can use HTML::FormHandler to manage forms, validate form input, and interface your forms with the database. .SH "Installation" .IX Header "Installation" Use \s-1CPAN\s0 to install HTML::FormHandler .SH "Use the Tutorial application" .IX Header "Use the Tutorial application" We'll use the files that were created in the Catalyst::Manual::Tutorial, in order to concentrate on just the bits where HTML::FormHandler is useful. You can download a tar file of the tutorial files from the Catalyst code repository. (See Catalyst::Manual::Tutorial::Intro.) .SS "Create an HTML::FormHandler form" .IX Subsection "Create an HTML::FormHandler form" Untar the tutorial and make a lib/MyApp/Form directory. In that directory create the file Book.pm. .PP .Vb 1 \& package MyApp::Form::Book; \& \& use utf8; # if using non\-latin1 languages \& \& use HTML::FormHandler::Moose; \& extends \*(AqHTML::FormHandler::Model::DBIC\*(Aq; \& \& has \*(Aq+item_class\*(Aq => ( default => \*(AqBook\*(Aq ); \& has_field \*(Aqtitle\*(Aq => ( type => \*(AqText\*(Aq ); \& has_field \*(Aqrating\*(Aq => ( type => \*(AqInteger\*(Aq ); \& has_field \*(Aqauthors\*(Aq => ( type => \*(AqMultiple\*(Aq, label_column => \*(Aqlast_name\*(Aq ); \& has_field \*(Aqsubmit\*(Aq => ( type => \*(AqSubmit\*(Aq, value => \*(AqSubmit\*(Aq ); \& \& no HTML::FormHandler::Moose; \& 1; .Ve .PP This is your Form class. The form initializes the 'item_class' to the source name of your DBIx::Class result class. The form's fields are defined with the 'has_field' sugar, or in a 'field_list'. The names of the fields should match a column, relationship, or other accessor in your DBIx::Class result class. .PP The basic fields have only a 'type', such as \&'Text', or 'Integer'. These types are actually the names of HTML::FormHandler::Field classes. \&'Text' and 'Integer' are types that are provided by HTML::FormHandler, in HTML::FormHandler::Field::Text and HTML::FormHandler::Field::Integer. .PP The 'Multiple' type will allow you to easily create a multiple select list from the 'authors' relationship. The 'label_column' attribute must be defined because the column in the 'authors' table which is used to create the select list does not have the default column name ('name'). .PP The 'submit' field is necessary if you are going to use FormHandler to render your form. It wouldn't be necessary for hand-built templates or \s-1HTML.\s0 .PP Eventually you will want to create your own field classes, but for this simple form the default types are adequate. .SS "Connect HTML::FormHandler to your controller" .IX Subsection "Connect HTML::FormHandler to your controller" Edit lib/MyApp/Controller/Books.pm. Add use Moose: .PP .Vb 3 \& use Moose; \& BEGIN { extends \*(AqCatalyst::Controller\*(Aq } \& use MyApp::Form::Book; .Ve .PP Create an attribute to hold your form: .PP .Vb 2 \& has \*(Aqform\*(Aq => ( isa => \*(AqMyApp::Form::Book\*(Aq, is => \*(Aqrw\*(Aq, \& lazy => 1, default => sub { MyApp::Form::Book\->new } ); .Ve .SS "Add Action to Display and Save the Form" .IX Subsection "Add Action to Display and Save the Form" In \f(CW\*(C`lib/MyApp/Controller/Books.pm\*(C'\fR add the following method: .PP .Vb 2 \& sub edit : Local { \& my ( $self, $c, $book_id ) = @_; \& \& $c\->stash( template => \*(Aqbooks/edit.tt2\*(Aq, \& form => $self\->form ); \& \& # Validate and insert/update database \& return unless $self\->form\->process( item_id => $book_id, \& params => $c\->req\->parameters, \& schema => $c\->model(\*(AqDB\*(Aq)\->schema ); \& \& # Form validated, return to the books list \& $c\->flash\->{status_msg} = \*(AqBook saved\*(Aq; \& $c\->res\->redirect($c\->uri_for(\*(Aqlist\*(Aq)); \& } .Ve .PP This will handle both creating new books, and updating old books. If \f(CW$book_id\fR is undefined, then HTML::FormHandler will create a new book from your form. If you pass in a DBIx::Class row object instead of a primary key, you don't need to specify the schema. .SS "Render the form" .IX Subsection "Render the form" Save a copy of \f(CW\*(C`root/src/books/edit.tt2\*(C'\fR and create a new file that contains only: .PP .Vb 1 \& [% form.render %] .Ve .SS "Alternative hand-built Template for the form (optional)" .IX Subsection "Alternative hand-built Template for the form (optional)" Although the automatic rendering works well, sometimes it's necessary to hand build \s-1HTML.\s0 This section contains an example of a Template Toolkit template that may be used to display a FormHandler form. .PP In some cases, you might want to use the rendering for just the field and build custom divs or tables or whatever around it: .PP .Vb 3 \&
\& [% form.render_field(\*(Aqbook\*(Aq) %] \&
.Ve .PP If you don't want to play with \s-1HTML\s0 at this point, you can skip ahead to the next section. .PP You could also use \s-1TT\s0 macros to do pretty sophisticated template generation. But for now, we'll stick to a straightforward \s-1TT\s0 template: .PP Delete the single statement in \f(CW\*(C`root/src/books/edit.tt2\*(C'\fR, and enter or copy the following: .PP .Vb 1 \& [% META title = \*(AqBook Form\*(Aq %] \& \& [% FOR field IN form.error_fields %] \& [% FOR error IN field.errors %] \&

\& [% field.label _ \*(Aq: \*(Aq _ error %]

\& [% END %] \& [% END %] \& \&
\&

\& [% f = form.field(\*(Aqtitle\*(Aq) %] \& \& \&

\&

\& [% f = form.field(\*(Aqrating\*(Aq) %] \& \& \&

\&

\& [% f = form.field(\*(Aqauthors\*(Aq) %] \& \& \&

\& \&
\& \&

Return to book list

.Ve .SS "Add links to access create and update actions" .IX Subsection "Add links to access create and update actions" Add a link to root/src/books/list.tt2 to allow you to edit an existing book, by changing the last cell in the book list: .PP .Vb 4 \& \& Delete| \& Edit \& .Ve .PP Change the link to create a book at the bottom of the file: .PP .Vb 3 \&

\& Create book \&

.Ve .SS "Test the HTML::FormHandler Create Form" .IX Subsection "Test the HTML::FormHandler Create Form" Start up the server for MyApp: .PP .Vb 1 \& $ script/myapp_server.pl .Ve .PP (You'll need to login with test01/mypass if you're using the packaged tutorial.) Click the new \*(L"Create book\*(R" link at the bottom to display the form. Fill in the fields and click submit. You should be returned to the Book List page with a \*(L"Book saved\*(R" message. .PP Magic! A new book has been created and saved to the database with very little code in your controller. .PP Click on the 'edit' links, and edit the existing books. Changes should be saved and displayed properly. Try to add an alphabetic character to the rating field. You should get an error message. .SS "Add additional attributes to your form's fields" .IX Subsection "Add additional attributes to your form's fields" We'll add a couple of 'label' attributes to the fields: .PP .Vb 3 \& has_field \*(Aqtitle\*(Aq => ( type => \*(AqText\*(Aq, label => \*(AqTitle of a Book\*(Aq ); \& has_field \*(Aqrating\*(Aq => ( type => \*(AqInteger\*(Aq, label => \*(AqRating (1\-5)\*(Aq ); \& has_field \*(Aqauthors\*(Aq => ( type => \*(AqMultiple\*(Aq, label_column => \*(Aqlast_name\*(Aq ); .Ve .PP If you want a new attribute in your fields, it's very easy to add it to your custom Field classes. .PP .Vb 3 \& package MyApp::Form::Field::Extra; \& use Moose; \& extends \*(AqHTML::FormHandler::Field\*(Aq; \& \& has \*(Aqmy_attribute\*(Aq => ( isa => Str, is => \*(Aqro\*(Aq ); \& \& 1; .Ve .PP Now if your Field classes inherit from this, you can have a 'my_attribute' attribute for all your fields. Or use a Moose role instead of inheritance. .PP You can also add attributes to the base FormHandler field class using Moose. This technique is described in HTML::FormHandler::Manual::Cookbook. .SH "HTML::FormHandler Validation" .IX Header "HTML::FormHandler Validation" Now we'll add more validation to ensure that users are entering correct data. .PP Update the fields in the form file: .PP .Vb 7 \& has_field \*(Aqtitle\*(Aq => ( type => \*(AqText\*(Aq, label => \*(AqTitle of a Book\*(Aq, \& required => 1, size => 40, minlength => 5 ); \& has_field \*(Aqrating\*(Aq => ( type => \*(AqInteger\*(Aq, label => \*(AqRating (1\-5)\*(Aq, \& required => 1, messages => { required => \*(AqYou must rate the book\*(Aq }, \& range_start => 1, range_end => 5 ); \& has_field \*(Aqauthors\*(Aq => ( type => \*(AqMultiple\*(Aq, label_column => \*(Aqlast_name\*(Aq, \& required => 1 ); .Ve .PP We've made all the fields required. We added 'size' and 'minlength' attributes to the 'title' field. These are attributes of the 'Text' Field, which will use them to validate. We've added 'range_start' and 'range_end' attributes to the 'rating' field. Numbers entered in the form will be checked to make sure they fall within the defined range. (Another option would have been to use the 'IntRange' field type, which makes it easy to create a select list of numbers.) .SS "Add customized validation" .IX Subsection "Add customized validation" You can create a Field class for validation that will be performed on more than one field, but it is easy to perform custom validation on a per-field basis. .PP This form doesn't really require any customized validation, so we'll add a silly field constraint. Add the following to the form: .PP .Vb 5 \& sub validate_title { \& my ( $self, $field ) = @_; \& $field\->add_error("The word \e\*(AqRainbows\e\*(Aq is not allowed in titles") \& if ( $field\->value =~ /Rainbows/ ); \& } .Ve .PP You can also apply Moose constraints and transforms. Validation can also be performed in a form 'validate_