[Catalyst] Feedback requested on HTML::FormHandler's new widget system

Gerda Shank gs364 at cornell.edu
Tue Sep 1 02:41:04 GMT 2009


A new widget system for HTML::FormHandler is currently under 
development, and it would be nice to get feedback from those who might 
be interested in it before putting it out in a release.

It's currently in the HTML::FormHandler repository on github:

http://github.com/gshank/html-formhandler/tree/master

I've copied the current version of HTML::FormHandler::Manual::Rendering 
at the end of this email.

Please respond offlist or on #formhandler.

Thanks,
Gerda Shank

=========================================

=head1 NAME

HTML::FormHandler::Manual::Rendering

=head1 SYNOPSIS

HFH has a number of different rendering methods.

   1. Handcoded html with no assist from HFH at all
   2. Use templates and the field 'widget' to determine the template snippet
   3. Use a rendering role in your form class, like Render::Simple

and now:

   4. Automatically installed rendering widgets using a combination of
      rendering roles, which can easily be customized by the user.

=head1 Rendering with Widgets

All FormHandler widgets are Moose roles.
Default widget roles are installed into HTML::FormHandler::Widget. They 
include
widgets for the fields in the distribution. Each field can render itself 
with
C<< $field->render >>. The widget rendering roles are applied at build 
time in
each field object.

The name space used to look for the widget roles can be specified on a 
form or
field basis by setting 'widget_name_space' to a scalar name space, like:

   has '+widget_name_space' => ( default => 'MyApp::Form::Widget' );

or to an arrayref of name spaces:

   has '+widget_name_space' => ( default => sub { ['MyApp::Form::Submit',
       'MyApp::Form::Widget' ]);

The HTML::FormHandler::Widget name space is always searched as the last 
name space.
This means that you can set up an application or form specific set of 
widgets.

Widgets in a widget directory (specified in widget_name_space) are 
located in either
a 'Field', 'Wrapper', or 'Form' subdirectory.

The form's rendering role is looked for in the widget name space plus 
'Form'. The
default form rendering roles are in HTML::FormHandler::Widget::Form. The 
form
widget is specified in the form with 'widget_form'.

   package MyApp::Form;
   ....
   has '+widget_form' => ( widget_form => 'Simple' );
   ...

The 'wrapper' for field rendering can also be specified with 
'widget_wrapper'.
The widget specified will be looked for in the widget directories' 'Wrapper'
subdirectory. It contains a 'wrap_field' method which is called from the 
Field
widgets.  The wrap_field method takes the basic rendered field (passed 
from the
field widget) and wraps it with HTML. The defaults provided are 'Div' 
and 'Table'.
You can specify a wrapper class for all the fields in the form by setting
'widget_wrapper' in the form class, or you can set them individually by 
setting
'widget_wrapper' on individual fields.

   has 'some_field' => ( widget_wrapper => 'MyWrapper' );
 
The 'widget' attribute is set to a default in FormHandler fields, or you 
can
set it to a different widget in your field declarations.

   has 'another_field' => ( widget => 'MyWidget', widget_wrapper => 
'MyWrapper' );

Can be set in the form:

   widget_name_space
   widget_wrapper
   widget_form

Can be set in the field:

   widget_name_space
   widget_wrapper
   widget

The widget_name_space and widget_wrapper will be copied into the fields 
from the
form if they are not already defined.

By default, a form will use the Form::Simple and Wrapper::Div widgets. 
If you
want to use the table format you can change the 'widget_form' and 
'widget_wrapper'
attributes in the form, or do it on new:

   my $form = MyApp::Form->new( widget_form => 'Table', widget_wrapper 
=> 'Table' );

The form widgets will not be applied if a 'render' method already exists 
in the form,
such as is the case when you've done a 'with' for 
L<HTML::FormHandler::Render::Simple>.

=head1 Customized Widgets

You can create custom widgets for your complete application or on a 
per-form basis.
One possible layout for your widgets;

   lib/MyApp/Form
   lib/MyApp/Form/Widget/Form
   lib/MyApp/Form/Widget/Field (contains MyWidget.pm)
   lib/MyApp/Form/Widget/Wrapper

Create custom widgets and put them in the respective directories, and 
then specify your
widget name space:

   MyApp::Form::User:
   ...
   has '+widget_name_space' => ( default => 'MyApp::Form::Widget' );
   ..
   has 'some_field' => ( widget => 'MyWidget' );

Your rendering widgets will be applied into your field classes.

=head1 Creating Widgets

The new widgets are designed to be used with either the original 
FormHandler
form objects or the new L<HTML::FormHandler::Result> objects. For that 
reason,
you should use C<< $field->result >> to access the current value, errors 
and
'fif' (fill-in-form) in field widgets, so that they will work
for both form and result rendering.

The basic structure for a field widget:

   package MyApp::Form::Widget::Field::MyWidget;
   use Moose::Role;

   sub render
   {
      my ( $self, $result ) = @_;

      $result ||= $self->result;
      my $output;
      < create rendered field >
      my $fif = $result->fif;
      my $value = $result->value;
      my $errors = $result->errors;
      < done creating rendered field )
      return $self->wrap_field($result, $output);
   }
   no Moose::Role;
   1;

=cut



More information about the Catalyst mailing list