Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
HTML::FormHandler::ManUser:Contributed PHTML::FormHandler::Manual::Tutorial(3)

NAME
       HTML::FormHandler::Manual::Tutorial - how to use	FormHandler with
       Catalyst

VERSION
       version 0.40067

SYNOPSIS
       Manual Index

       A tutorial for beginners	to HTML::FormHandler

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.

Installation
       Use CPAN	to install HTML::FormHandler

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.)

   Create an HTML::FormHandler form
       Untar the tutorial and make a lib/MyApp/Form directory. In that
       directory create	the file Book.pm.

	  package MyApp::Form::Book;

	  use utf8; # if using non-latin1 languages

	  use HTML::FormHandler::Moose;
	  extends 'HTML::FormHandler::Model::DBIC';

	  has '+item_class' => ( default => 'Book' );
	  has_field 'title' => ( type => 'Text'	);
	  has_field 'rating' =>	( type => 'Integer' );
	  has_field 'authors' => ( type	=> 'Multiple', label_column => 'last_name' );
	  has_field 'submit' =>	( type => 'Submit', value => 'Submit' );

	  no HTML::FormHandler::Moose;
	  1;

       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.

       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.

       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').

       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
       HTML.

       Eventually you will want	to create your own field classes, but for this
       simple form the default types are adequate.

   Connect HTML::FormHandler to	your controller
       Edit lib/MyApp/Controller/Books.pm.  Add	use Moose:

	   use Moose;
	   BEGIN { extends 'Catalyst::Controller' }
	   use MyApp::Form::Book;

       Create an attribute to hold your	form:

	  has 'form' =>	( isa => 'MyApp::Form::Book', is => 'rw',
	      lazy => 1, default => sub	{ MyApp::Form::Book->new } );

   Add Action to Display and Save the Form
       In "lib/MyApp/Controller/Books.pm" add the following method:

	   sub edit : Local {
	       my ( $self, $c, $book_id	) = @_;

	       $c->stash( template => 'books/edit.tt2',
			  form => $self->form );

	       # Validate and insert/update database
	       return unless $self->form->process( item_id => $book_id,
		  params => $c->req->parameters,
		  schema => $c->model('DB')->schema );

	       # Form validated, return	to the books list
	       $c->flash->{status_msg} = 'Book saved';
	       $c->res->redirect($c->uri_for('list'));
	   }

       This will handle	both creating new books, and updating old books.  If
       $book_id	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.

   Render the form
       Save a copy of "root/src/books/edit.tt2"	and create a new file that
       contains	only:

	  [% form.render %]

   Alternative hand-built Template for the form	(optional)
       Although	the automatic rendering	works well, sometimes it's necessary
       to hand build HTML. This	section	contains an example of a Template
       Toolkit template	that may be used to display a FormHandler form.

       In some cases, you might	want to	use the	rendering for just the field
       and build custom	divs or	tables or whatever around it:

	 <div class="mycustomclass">
	 [% form.render_field('book') %]
	 </div>

       If you don't want to play with HTML at this point, you can skip ahead
       to the next section.

       You could also use TT macros to do pretty sophisticated template
       generation. But for now,	we'll stick to a straightforward TT template:

       Delete the single statement in "root/src/books/edit.tt2", and enter or
       copy the	following:

	  [% META title	= 'Book	Form' %]

	  [% FOR field IN form.error_fields %]
	    [% FOR error IN field.errors %]
	      <p><span class="error" id="error">
		 [% field.label	_ ': ' _ error %] </span></p>
	    [% END %]
	  [% END %]

	  <form	name="[% form.name %]"
		action="[% c.uri_for('edit', form.item_id) %]"
		method="post">
	  <p>
	  [% f = form.field('title') %]
	  <label class="label" for="[% f.name %]">[% f.label %]:</label>
	  <input type="text" name="[% f.name %]" id="[%	f.name %]" value="[% f.fif %]">
	  </p>
	  <p>
	  [% f = form.field('rating') %]
	  <label class="label" for="[% f.name %]">[% f.label %]:</label>
	  <input type="text" name="[% f.name %]" id="[%	f.name %]" %] value="[%	f.fif %]">
	  </p>
	  <p>
	  [% f = form.field('authors') %]
	  <label class="label" for="[% f.name %]">[% f.label %]:</label>
	  <select name="[% f.name %]" multiple="multiple" size="[% f.size %]">
	    [% FOR option IN f.options %]
	      <option value="[%	option.value %]"
		[% FOREACH selval IN f.fif %]
		    [% IF selval == option.value %]selected="selected"[% END %]
		[% END %]>
	      [% option.label |	html %]</option>
	    [% END %]
	  </select>
	  </p>
	  <input class="button"	name="submit" type="submit" value="Submit" />
	  </form>

	  <p><a	href="[% c.uri_for('list') %]">Return to book list</a></p>

   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 <td> cell in the book	list:

	  <td>
	     <a	href="[% c.uri_for('delete', book.id) %]">Delete</a>|
	     <a	href="[% c.uri_for('edit', book.id) %]">Edit</a>
	  </td>

       Change the link to create a book	at the bottom of the file:

	   <p>
	     <a	href="[% c.uri_for('edit') %]">Create book</a>
	   </p>

   Test	the HTML::FormHandler Create Form
       Start up	the server for MyApp:

	   $ script/myapp_server.pl

       (You'll need to login with test01/mypass	if you're using	the packaged
       tutorial.) Click	the new	"Create	book" 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 "Book saved" message.

       Magic! A	new book has been created and saved to the database with very
       little code in your controller.

       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.

   Add additional attributes to	your form's fields
       We'll add a couple of 'label' attributes	to the fields:

	  has_field 'title' => ( type => 'Text', label => 'Title of a Book' );
	  has_field 'rating' =>	( type => 'Integer', label => 'Rating (1-5)' );
	  has_field 'authors' => ( type	=> 'Multiple', label_column => 'last_name' );

       If you want a new attribute in your fields, it's	very easy to add it to
       your custom Field classes.

	  package MyApp::Form::Field::Extra;
	  use Moose;
	  extends 'HTML::FormHandler::Field';

	  has 'my_attribute' =>	( isa => Str, is => 'ro' );

	  1;

       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.

       You can also add	attributes to the base FormHandler field class using
       Moose.  This technique is described in
       HTML::FormHandler::Manual::Cookbook.

HTML::FormHandler Validation
       Now we'll add more validation to	ensure that users are entering correct
       data.

       Update the fields in the	form file:

	  has_field 'title' => ( type => 'Text', label => 'Title of a Book',
	     required => 1, size => 40,	minlength => 5 );
	  has_field 'rating' =>	( type => 'Integer', label => 'Rating (1-5)',
	     required => 1, messages =>	{ required => 'You must	rate the book' },
	     range_start => 1, range_end => 5 );
	  has_field 'authors' => ( type	=> 'Multiple', label_column => 'last_name',
	     required => 1 );

       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.)

   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.

       This form doesn't really	require	any customized validation, so we'll
       add a silly field constraint.  Add the following	to the form:

	  sub validate_title {
	     my	( $self, $field	) = @_;
	     $field->add_error("The word \'Rainbows\' is not allowed in	titles")
		if ( $field->value =~ /Rainbows/ );
	  }

       You can also apply Moose	constraints and	transforms. Validation can
       also be performed in a form 'validate_<field_name' method, in a
       'validate_model'	routine, and in	a custom field class.  You can
       validate	that the field is unique, or use a dependency list to make
       more fields required if one is updated.

   Check out the validation
       Restart the development server, login, and try adding books with
       various errors: title length less than 5	or more	than 40, rating	above
       5, leaving out a	particular field.  Create a book with 'Rainbows' in
       the title.

       You should get error messages for every error.

AUTHOR
       FormHandler Contributors	- see HTML::FormHandler

COPYRIGHT AND LICENSE
       This software is	copyright (c) 2016 by Gerda Shank.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.24.1			  2016-1HTML::FormHandler::Manual::Tutorial(3)

NAME | VERSION | SYNOPSIS | Using HTML::FormHandler with Catalyst | Installation | Use the Tutorial application | HTML::FormHandler Validation | AUTHOR | COPYRIGHT AND LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=HTML::FormHandler::Manual::Tutorial&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help