FAQ
I have been working away on a module called CGI::FormManager for a
couple of months now (I registered it with CPAN a month or so ago and
gave a talk on it at the Birminham perl mongers meeting at the end of
October). The module is intended to render forms from definitions of
the forms and validate submitted data against those definitions. It is
inspired in part by CGI:FormBuilder, but delegates validation to
Data::FormValidator. I intend to use it with Catalyst and Template
Toolkit, but of course its application is wider than that.

Given that the module works with Catalyst I am making a first
announcement of version 0.04 here. The source code is available from:

http://andrew-ford.com/perl/cgi-formmanager/

Bear in mind that this is alpha-stage code -- I may change any aspect of
it at the moment, although I do have a client using an even earlier
version on a production web site.

I've attached an introduction to the module below.

I would welcome comments on the design and on any other aspect of it.

Andrew



NAME
CGI::FormManager::Manual::Intro - introduction to the Form Manager

INTRODUCTION
Coding for CGI forms is tedious. Often an application that accepts user
data will display an initial version of a form, check the user's data
then display another version of the form indicating errors in the data;
then when the data passes all validation checks it may display a
confirmation page containing the user's data, allowing the user to
confirm, cancel or go back and edit the data.

That is a lot of code - a lot of very tedious code. What I would prefer
to have is a definition of the structure of the form and have all the
code generated for me. This is what "CGI::FormManager" attempts to do --
it manages forms, validating and rendering them. It is inspired by
"Data::FormValidator" and "CGI::FormBuilder".

The module renders form with initial data, with data submitted by the
user, and will also render a confirmation form. It uses an internal
default templates render form using tables (this may change to CSS at
some stage). By default forms are laid out with the labels in one column
and the fields in the next column, but there are also facilities to deal
with repeating groups of elements (such as a checkout form), and I am
thinking of providing the facility to specify groups of fields (for
example for a billing address and a shipping address laid out side by
side).

Validation is delegated to "Data::FormValidator", but the form
validation profile specified is augmented with information derived from
the definition of the fields making up the form.

NOTE: this module is still experimental and in a state of flux. I am
still playing with the API and the manner of declaring forms, and am
trying to get it all to "feel right".

AN EXAMPLE
Our example application is a fairly typical user registration
application with an initial data entry page and a data confirmation
page. The application uses Template Toolkit for rendering and Catalyst
as the application framework.

The HTML Templates
The template for the initial data entry page would look like:

<h1>Sample App</h1>

<p>Some instructions here.</p>
<p>Please fill in this form:</p>

[% form %]

Our Template Toolkit setup will wrap the output of the template in
"<html>" and "<body>" elements, and insert a "<head>" element and all
the other paraphernalia to give a complete HTML document.

The "form" variable is set up in the application code, which we will
come to later. It is a "CGI::FormManager::Form" object and as such
renders itself as HTML in a string context.

If there are errors in the data submitted then we go to the corrections
page:

<h1>Sample App</h1>

<p>There were some problems with the data you entered</p>
<p>[% message %]</p>

[% form %]

Of course this fragment and the previous one are so similar that one
might want to roll them together. [EXPAND]

When we are happy with the data we display the confirmation form:

<h1>Sample App</h1>

<p>Thank you for entering your details. Please check the data
you entered and click confirm, edit or cancel,</p>

[% form.render_confirmation %]

The Form Definition
The form is defined in a hash passed to the "CGI::FormManager" package.
The hash contains three elements: "options", "elements" and
"validation".

This is what our form definition might look like:

my $form_defn = {
options => { method => 'POST',
action => $url,
},
elements => [ '<h2>Your login credentials</h2>',
cfm_text_field( name => 'email',
label => 'Email address',
size => 40,
maxlength => 50,
constraint => email()
REQUIRED ),
cfm_password_field( name => 'password',
REQUIRED),
cfm_password_field( name => 'password2',
label => 'Repeat your
password',
REQUIRED),

'<h2>Personal Details</h2>',
cfm_text_field( name => 'first_name',
REQUIRED ),
...

],
validation => { required => [ qw(email password) ],
constraint_methods => {
email => email(),
},
},
};

The "options" element is fairly self-explanatory, specifying the URL for
the form and that the form should be submitted with a POST request.

The "elements" element lists the "elements" that make up the form.
"CGI::FormManager" exports a set of subroutines for creating form
elements of different types; any plain text strings are regarded as a
literal text to be included in the form. Fields are named and may have a
label, which will be included in front of the field element in the HTML
document. If no label is specified then a label is created from the
field name by upper-casing the first letter and replacing underscores
with spaces. Constraints may be specified in the field constructors or
may be specified in the "validation" element.

The "validation" element specifies how the form should be validated. It
is augmented with information inferred from the field elements and
passed to "Data::FormValidator" when the form is validated.

The Application Code
The sample application is a Catalyst application, using a Template
Toolkit view component. See the Catalyst documentation for more
information.

The main application package instantiates a "CGI::FormManager" object to
manage the forms (which are defined in the controller packages), storing
it in the application's configuration and then sets up the Catalyst
application.

package MyRegApp;

use strict;
use Catalyst qw/-Debug/;

use CGI::FormManager;

MyRegApp->config( name => 'MyRegApp',
fmgr => CGI::FormManager->new() );
MyRegApp->setup;

sub end : Global {
my ($self, $c) = @_;
$c->stash->{template} ||= "default.tt2";
$c->forward('MyRegApp::View::TT') unless $c->res->output;
die if $c->req->params->{die};
}

1;

Registration is handled in a Catalyst controller package. It defines the
form and loads it into the form manager (which it picks out of the
application's configuration) as the package is loaded. Handling
registration requests is done in the "user_details" action routine.

package MyRegApp::Controller::Registration;

use strict;
use base 'Catalyst::Base';
use CGI::FormManager qw(:element_decls :constraint_methods);

my $form_defn = ...; # (defined above)

MyRegApp->config->{'fmgr'}->add_form(user_details => $form_defn);

sub default : Private {
my($self, $c) = @_;
$c->forward('user_details');
}

sub user_details : Local {
my($self, $c) = @_;
my $form = $c->config->{fmgr}->form('user_details');
my $params = $c->request->params;
my $stash = $c->stash;

if (!keys %$params) {
$c->stash->{template} = "registration/new_user.tt2";
}
else {
$form = $form->validate($params);
if (!$form) {
$c->log->debug("validation failed" );
$c->log->debug(" missing:" . join(", ", $form->missing));
$c->log->debug(" invalid:" . join(", ", $form->invalid));
$c->stash->{template} = "registration/new_user_corrections.tt2";
$c->stash->{message} = <<EOS;
There are problems with the information you supplied,
please correct these and resubmit.
EOS
}
else {
$c->log->debug("validation passed");
if ($form->confirmed_data) {
# store the new user in the database
$c->stash->{template} = "registration/welcome.tt2";
}
else {
$c->stash->{template} = "registration/new_user_confirm.tt2";
}
}
$c->stash->{form} = $form;
}
}

The action method fetches the form object.

If there were no parameters then it is a new request so it sets the
template to be used to be the new user form page. Otherwise it gets the
form manager to validate the parameters supplied against the form
definition.

If validation fails then the corrections template is used, otherwise we
look and see if it was a confirmation form that was submitted. If we
have come from the confirmation page then create the new user and
display a welcome page, otherwise display the confirmation page.
(Actually this routine doesn't included code for handling the user
clicking on "edit" or "cancel" on the confirmation page, or the actual
user creation, but you get the idea.)

The general form of an action method is:

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

# Set up the template we are going to use (may be updated later)
$c->stash->{template} = 'template-name';

# Validate the submitted data against the form
my $results = $fmgr->validate(form1 => $c->request);

# Make the form-results object visible to the template
$c->stash->{form} = $results;

if ($results) {
# The data is valid (NB evaluating $results in a boolean
# context is the same as $results->success)

if ($results->confirmed_data) {
# do something with the data, according to whether
# the user clicked "confirm", "edit" or "cancel"
# (will need change the template used)
}
else {
# data is OK, might want the user to confirm
$c->stash->{template} = 'form1-confirm-template';
}
}
elsif ($results->submitted) {
# Data was received but is not valid -- do nothing and the
# form will be redisplayed with appropriate error messages.
# Note though that if $results->confirmed_data is true then
# there may be a problem -- the confirmation form was
# submitted but the data stored in hidden fields might
# have been modified maliciously.
}
else {
# no data was received so just display the initial form
}
}

OTHER FEATURES
Lookup Elements
These elements allow text to be generated by a callback routine.

Repeating Groups of Fields
Applications such as shopping carts require the ability to display
repeating groups of form elements. This is the syntax I have come up
with:

cfm_repeating_group( elements =>
[ cfm_hidden_field ( name => 'prodcode' ),
cfm_lookup_element( name => 'desc',
header => 'Description',
value => \&_row_description ),
cfm_text_field ( name => 'qty',
header => 'Quantity'),
cfm_lookup_element( name => 'price',
value => \&_row_price ),
cfm_lookup_element( name => 'line_total',
value => \&_row_total,
footers => [ \&_sub_total,
\&_postage,
\&_tax,
\&_total ] )
],

This will be rendered as a table of four columns (the hidden field will
be prepended to the contents of the first column). The number of rows
will be determined from the form data and there will be four footer rows
for the calculated cells specified on the line total element.

OUTSTANDING ISSUES
This software should be considered alpha quality. It has not been
extensively tested and the exact details of the API have not been
finalized. However there are applications using it that are in
production use!

This is a partial list of outstanding issues.

* expand the documentation

* complete the initialization of form field objects (defaults, cross
population of validation/elements, radio field groups, etc)

* review the use of CSS classes on elements

* automatically generate JavaScript validation code (as
"CGI::FormBuilder" does)

* add objects to group elements -- for example for side-by-side layout
of billing and shipping addresses.

* expand the test suite

* design a proper Catalyst plugin

* have textual representation of form specification that can be read

SEE ALSO
Data::FormValidator, Template, CGI::FormBuilder

AUTHOR
Andrew Ford <A.Ford@ford-mason.co.uk>

COPYRIGHT
This program is free software, you can redistribute it and/or modify it
under the same terms as Perl itself.

Search Discussions

  • Bernard FRIT at Nov 22, 2005 at 3:40 pm
    Andrew,

    2005/11/22, Andrew Ford <A.Ford@ford-mason.co.uk>:
    Given that the module works with Catalyst I am making a first
    announcement of version 0.04 here. The source code is available from:

    http://andrew-ford.com/perl/cgi-formmanager/
    Thanks for your release.
    This is what our form definition might look like:

    my $form_defn = {
    options => { method => 'POST',
    action => $url,
    },
    elements => [ '<h2>Your login credentials</h2>',
    cfm_text_field( name => 'email',
    label => 'Email address',
    ...

    ],
    validation => { required => [ qw(email password) ],
    constraint_methods => {
    email => email(),
    },
    },
    };
    Do you think that form definition data could be reasonably loaded from
    say a YAML file or whatever in the flavor of formbuilder source
    directive?

    --
    Bernard FRIT
  • Andrew Ford at Nov 22, 2005 at 3:49 pm

    Bernard FRIT wrote:
    Andrew,

    2005/11/22, Andrew Ford <A.Ford@ford-mason.co.uk>:


    Given that the module works with Catalyst I am making a first
    announcement of version 0.04 here. The source code is available from:

    http://andrew-ford.com/perl/cgi-formmanager/
    Thanks for your release.


    This is what our form definition might look like:

    my $form_defn = {
    options => { method => 'POST',
    action => $url,
    },
    elements => [ '<h2>Your login credentials</h2>',
    cfm_text_field( name => 'email',
    label => 'Email address',
    ...

    ],
    validation => { required => [ qw(email password) ],
    constraint_methods => {
    email => email(),
    },
    },
    };
    Do you think that form definition data could be reasonably loaded from
    say a YAML file or whatever in the flavor of formbuilder source
    directive?

    I was taken by the idea of the CGI::FormBuilder::Source modules and was
    wondering whether something like that might be feasible. I'll put it on
    my wish-list.

    At the moment I am trying to get a feel for the possibilities and
    limitations of the approach of my module, and there are several areas
    still needing fleshing out.

    Regards
    Andrew

    --
    Andrew Ford, Director Pauntley Prints / Ford & Mason Ltd
    A.Ford@ford-mason.co.uk South Wing Compton House
    pauntley-prints.co.uk Compton Green, Redmarley Tel: +44 1531 829900
    ford-mason.co.uk Gloucester GL19 3JB Fax: +44 1531 829901
    refcards.com cronolog.org Great Britain Mobile: +44 7785 258278
  • Sascha Kiefer at Nov 22, 2005 at 3:50 pm
    well, the best would be to wrap it into a Catalyst::Plugin as usual.
    --esskar

    Bernard FRIT schrieb:
    Given that the module works with Catalyst I am making a first
    announcement of version 0.04 here. The source code is available from:

    http://andrew-ford.com/perl/cgi-formmanager/
    Do you think that form definition data could be reasonably loaded from
    say a YAML file or whatever in the flavor of formbuilder source
    directive?
  • John Lifsey at Nov 22, 2005 at 4:22 pm
    It may be covered by your callback idea, but if I were using it I'm sure
    I would want to arrange the form how I liked (or more correctly, someone
    with a clue about interface would arrange it). Would something like this
    be possible?

    [% form.start %]
    <table><tr><td>Your email address:</td><td>[% form.email
    %]</td></tr></table>
    [% form.stop %]

    So that formmanager (gener/valid)ates the form elements, but the
    structure can be changed?

    John

    Andrew Ford wrote:
    I have been working away on a module called CGI::FormManager for a
    couple of months now (I registered it with CPAN a month or so ago and
    gave a talk on it at the Birminham perl mongers meeting at the end of
    October). The module is intended to render forms from definitions of
    the forms and validate submitted data against those definitions. It
    is inspired in part by CGI:FormBuilder, but delegates validation to
    Data::FormValidator. I intend to use it with Catalyst and Template
    Toolkit, but of course its application is wider than that.

    Given that the module works with Catalyst I am making a first
    announcement of version 0.04 here. The source code is available from:

    http://andrew-ford.com/perl/cgi-formmanager/

    Bear in mind that this is alpha-stage code -- I may change any aspect
    of it at the moment, although I do have a client using an even earlier
    version on a production web site.

    I've attached an introduction to the module below.

    I would welcome comments on the design and on any other aspect of it.

    Andrew



    NAME
    CGI::FormManager::Manual::Intro - introduction to the Form Manager

    INTRODUCTION
    Coding for CGI forms is tedious. Often an application that accepts
    user
    data will display an initial version of a form, check the user's data
    then display another version of the form indicating errors in the
    data;
    then when the data passes all validation checks it may display a
    confirmation page containing the user's data, allowing the user to
    confirm, cancel or go back and edit the data.

    That is a lot of code - a lot of very tedious code. What I would
    prefer
    to have is a definition of the structure of the form and have all the
    code generated for me. This is what "CGI::FormManager" attempts to
    do --
    it manages forms, validating and rendering them. It is inspired by
    "Data::FormValidator" and "CGI::FormBuilder".

    The module renders form with initial data, with data submitted by the
    user, and will also render a confirmation form. It uses an internal
    default templates render form using tables (this may change to CSS at
    some stage). By default forms are laid out with the labels in one
    column
    and the fields in the next column, but there are also facilities to
    deal
    with repeating groups of elements (such as a checkout form), and I am
    thinking of providing the facility to specify groups of fields (for
    example for a billing address and a shipping address laid out side by
    side).

    Validation is delegated to "Data::FormValidator", but the form
    validation profile specified is augmented with information derived
    from
    the definition of the fields making up the form.

    NOTE: this module is still experimental and in a state of flux. I am
    still playing with the API and the manner of declaring forms, and am
    trying to get it all to "feel right".

    AN EXAMPLE
    Our example application is a fairly typical user registration
    application with an initial data entry page and a data confirmation
    page. The application uses Template Toolkit for rendering and Catalyst
    as the application framework.

    The HTML Templates
    The template for the initial data entry page would look like:

    <h1>Sample App</h1>

    <p>Some instructions here.</p>
    <p>Please fill in this form:</p>

    [% form %]

    Our Template Toolkit setup will wrap the output of the template in
    "<html>" and "<body>" elements, and insert a "<head>" element and all
    the other paraphernalia to give a complete HTML document.

    The "form" variable is set up in the application code, which we will
    come to later. It is a "CGI::FormManager::Form" object and as such
    renders itself as HTML in a string context.

    If there are errors in the data submitted then we go to the
    corrections
    page:

    <h1>Sample App</h1>

    <p>There were some problems with the data you entered</p>
    <p>[% message %]</p>

    [% form %]

    Of course this fragment and the previous one are so similar that one
    might want to roll them together. [EXPAND]

    When we are happy with the data we display the confirmation form:

    <h1>Sample App</h1>

    <p>Thank you for entering your details. Please check the data
    you entered and click confirm, edit or cancel,</p>

    [% form.render_confirmation %]

    The Form Definition
    The form is defined in a hash passed to the "CGI::FormManager"
    package.
    The hash contains three elements: "options", "elements" and
    "validation".

    This is what our form definition might look like:

    my $form_defn = {
    options => { method => 'POST',
    action => $url,
    },
    elements => [ '<h2>Your login credentials</h2>',
    cfm_text_field( name => 'email',
    label => 'Email address',
    size => 40,
    maxlength => 50,
    constraint => email()
    REQUIRED ),
    cfm_password_field( name => 'password',
    REQUIRED),
    cfm_password_field( name => 'password2',
    label => 'Repeat your
    password',
    REQUIRED),

    '<h2>Personal Details</h2>',
    cfm_text_field( name => 'first_name',
    REQUIRED ),
    ...

    ],
    validation => { required => [ qw(email password) ],
    constraint_methods => {
    email => email(),
    },
    },
    };

    The "options" element is fairly self-explanatory, specifying the
    URL for
    the form and that the form should be submitted with a POST request.

    The "elements" element lists the "elements" that make up the form.
    "CGI::FormManager" exports a set of subroutines for creating form
    elements of different types; any plain text strings are regarded as a
    literal text to be included in the form. Fields are named and may
    have a
    label, which will be included in front of the field element in the
    HTML
    document. If no label is specified then a label is created from the
    field name by upper-casing the first letter and replacing underscores
    with spaces. Constraints may be specified in the field constructors or
    may be specified in the "validation" element.

    The "validation" element specifies how the form should be
    validated. It
    is augmented with information inferred from the field elements and
    passed to "Data::FormValidator" when the form is validated.

    The Application Code
    The sample application is a Catalyst application, using a Template
    Toolkit view component. See the Catalyst documentation for more
    information.

    The main application package instantiates a "CGI::FormManager"
    object to
    manage the forms (which are defined in the controller packages),
    storing
    it in the application's configuration and then sets up the Catalyst
    application.

    package MyRegApp;

    use strict;
    use Catalyst qw/-Debug/;

    use CGI::FormManager;

    MyRegApp->config( name => 'MyRegApp',
    fmgr => CGI::FormManager->new() );
    MyRegApp->setup;

    sub end : Global {
    my ($self, $c) = @_;
    $c->stash->{template} ||= "default.tt2";
    $c->forward('MyRegApp::View::TT') unless $c->res->output;
    die if $c->req->params->{die};
    }

    1;

    Registration is handled in a Catalyst controller package. It
    defines the
    form and loads it into the form manager (which it picks out of the
    application's configuration) as the package is loaded. Handling
    registration requests is done in the "user_details" action routine.

    package MyRegApp::Controller::Registration;

    use strict;
    use base 'Catalyst::Base';
    use CGI::FormManager qw(:element_decls :constraint_methods);

    my $form_defn = ...; # (defined above)

    MyRegApp->config->{'fmgr'}->add_form(user_details => $form_defn);

    sub default : Private {
    my($self, $c) = @_;
    $c->forward('user_details');
    }

    sub user_details : Local {
    my($self, $c) = @_;
    my $form = $c->config->{fmgr}->form('user_details');
    my $params = $c->request->params;
    my $stash = $c->stash;

    if (!keys %$params) {
    $c->stash->{template} = "registration/new_user.tt2";
    }
    else {
    $form = $form->validate($params);
    if (!$form) {
    $c->log->debug("validation failed" );
    $c->log->debug(" missing:" . join(", ", $form->missing));
    $c->log->debug(" invalid:" . join(", ", $form->invalid));
    $c->stash->{template} =
    "registration/new_user_corrections.tt2";
    $c->stash->{message} = <<EOS;
    There are problems with the information you supplied,
    please correct these and resubmit.
    EOS
    }
    else {
    $c->log->debug("validation passed");
    if ($form->confirmed_data) {
    # store the new user in the database
    $c->stash->{template} = "registration/welcome.tt2";
    }
    else {
    $c->stash->{template} = "registration/new_user_confirm.tt2";
    }
    }
    $c->stash->{form} = $form;
    }
    }

    The action method fetches the form object.

    If there were no parameters then it is a new request so it sets the
    template to be used to be the new user form page. Otherwise it gets
    the
    form manager to validate the parameters supplied against the form
    definition.

    If validation fails then the corrections template is used,
    otherwise we
    look and see if it was a confirmation form that was submitted. If we
    have come from the confirmation page then create the new user and
    display a welcome page, otherwise display the confirmation page.
    (Actually this routine doesn't included code for handling the user
    clicking on "edit" or "cancel" on the confirmation page, or the actual
    user creation, but you get the idea.)

    The general form of an action method is:

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

    # Set up the template we are going to use (may be updated later)
    $c->stash->{template} = 'template-name';

    # Validate the submitted data against the form
    my $results = $fmgr->validate(form1 => $c->request);

    # Make the form-results object visible to the template
    $c->stash->{form} = $results;

    if ($results) {
    # The data is valid (NB evaluating $results in a boolean
    # context is the same as $results->success)

    if ($results->confirmed_data) {
    # do something with the data, according to whether
    # the user clicked "confirm", "edit" or "cancel"
    # (will need change the template used)
    }
    else {
    # data is OK, might want the user to confirm
    $c->stash->{template} = 'form1-confirm-template';
    }
    }
    elsif ($results->submitted) {
    # Data was received but is not valid -- do nothing and the
    # form will be redisplayed with appropriate error messages.
    # Note though that if $results->confirmed_data is true then
    # there may be a problem -- the confirmation form was
    # submitted but the data stored in hidden fields might
    # have been modified maliciously.
    }
    else {
    # no data was received so just display the initial form
    }
    }

    OTHER FEATURES
    Lookup Elements
    These elements allow text to be generated by a callback routine.

    Repeating Groups of Fields
    Applications such as shopping carts require the ability to display
    repeating groups of form elements. This is the syntax I have come up
    with:

    cfm_repeating_group( elements =>
    [ cfm_hidden_field ( name => 'prodcode' ),
    cfm_lookup_element( name => 'desc',
    header => 'Description',
    value => \&_row_description ),
    cfm_text_field ( name => 'qty',
    header => 'Quantity'),
    cfm_lookup_element( name => 'price',
    value => \&_row_price ),
    cfm_lookup_element( name => 'line_total',
    value => \&_row_total,
    footers => [ \&_sub_total,
    \&_postage,
    \&_tax,
    \&_total ] )
    ],

    This will be rendered as a table of four columns (the hidden field
    will
    be prepended to the contents of the first column). The number of rows
    will be determined from the form data and there will be four footer
    rows
    for the calculated cells specified on the line total element.

    OUTSTANDING ISSUES
    This software should be considered alpha quality. It has not been
    extensively tested and the exact details of the API have not been
    finalized. However there are applications using it that are in
    production use!

    This is a partial list of outstanding issues.

    * expand the documentation

    * complete the initialization of form field objects (defaults, cross
    population of validation/elements, radio field groups, etc)

    * review the use of CSS classes on elements

    * automatically generate JavaScript validation code (as
    "CGI::FormBuilder" does)

    * add objects to group elements -- for example for side-by-side
    layout
    of billing and shipping addresses.

    * expand the test suite

    * design a proper Catalyst plugin

    * have textual representation of form specification that can be read

    SEE ALSO
    Data::FormValidator, Template, CGI::FormBuilder

    AUTHOR
    Andrew Ford <A.Ford@ford-mason.co.uk>

    COPYRIGHT
    This program is free software, you can redistribute it and/or
    modify it
    under the same terms as Perl itself.



    _______________________________________________
    Catalyst mailing list
    Catalyst@lists.rawmode.org
    http://lists.rawmode.org/mailman/listinfo/catalyst
  • Andrew Ford at Nov 22, 2005 at 4:57 pm

    John Lifsey - Contractor - wrote:

    It may be covered by your callback idea, but if I were using it I'm
    sure I would want to arrange the form how I liked (or more correctly,
    someone with a clue about interface would arrange it). Would something
    like this be possible?

    [% form.start %]
    <table><tr><td>Your email address:</td><td>[% form.email
    %]</td></tr></table>
    [% form.stop %]

    So that formmanager (gener/valid)ates the form elements, but the
    structure can be changed?

    The CGI::FormManager::Form package has two default TT2 templates - one
    for the fill-in form (with or without error messages) and the other for
    the confirmation form, however you can specify your own templates:

    my $fmgr = CGI::FormManager->new({}, { template => $mytemplate,

    confirm_template => $myconfirmtemplate });
    # add a form using our own templates
    my $form1 = $fmgr->form(myform1 => { elements => [ .. ] } );
    # add another form using another pair of templates
    my $form1 = $fmgr->form(myform2 => { elements => [ .. ],

    options => { template => $mytemplate2,

    confirm_temlate => ... } );

    The other thing is that the elements of the default templates are
    labelled with classes, so that you should be able to adapt the styling
    quite precisely using CSS.

    Of course there are issues like the ordering of fields and literal text
    within the form that might be up for discussion between the interface
    designer and the programmer, and this module sticks such things in the
    code. Maybe I could separate out the definition of the form fields, and
    the definition of the ordering of the fields within the form. I'll
    think about this.

    Regards
    Andrew
  • Peter Edwards at Nov 22, 2005 at 4:58 pm

    2005/11/22, Andrew Ford <A.Ford@ford-mason.co.uk>:
    Given that the module works with Catalyst I am making a first
    announcement of version 0.04 here. The source code is available from:

    http://andrew-ford.com/perl/cgi-formmanager/
    Looks good, just the sort of thing I need.
    I've got Catalyst set up and need to make a business application. The
    ServerDB example is a good start. Now I'm trying to figure out the best way
    to build on that.

    Bernard FRIT wrote:
    Do you think that form definition data could be reasonably loaded from
    say a YAML file or whatever in the flavor of formbuilder source
    directive?
    I had been thinking along these lines:
    Use an XML / YAML screen definition file that is rendered at run time into a
    TT2 template, looking up field labels, constraints and any special
    Javascript handling from a data dictionary. I guess I might need to cache
    the compiled templates and re-generate them if the code detects the
    definition has changed.
    One level above this, for each screen hold multiple definitions, say against
    user, team or company, to tailor the appearance of the application. This
    would let users pick dynamically the fields they want to see on screen.
    (Yes, I'm being bitten because of hard coded screens.)
    Based on the virtual host name vary how the app looks and works, use
    alternate dictionaries and make Internationalization easier.
    I'm not trying to re-invent ColdFusion here but save on Apache instances,
    though there might be scope for a screen definition editor later on to save
    time typing {}s for many screens.

    All this is a tier or two above Catalyst in package terms.
    I'm not sure where the best place is to discuss this sort of thing?
    It seems a fairly common set of requirements when writing a business system
    and I don't want to reinvent any wheels.

    Thanks, Peter
  • John Siracusa at Nov 22, 2005 at 8:06 pm

    On 11/22/05 10:28 AM, John Lifsey - Contractor - wrote:
    It may be covered by your callback idea, but if I were using it I'm sure
    I would want to arrange the form how I liked (or more correctly, someone
    with a clue about interface would arrange it). Would something like this
    be possible?

    [% form.start %]
    <table><tr><td>Your email address:</td><td>[% form.email
    %]</td></tr></table>
    [% form.stop %]

    So that formmanager (gener/valid)ates the form elements, but the
    structure can be changed?
    ...and so the convergence towards Rose::HTML::Objects continues ;) Okay,
    I'm mostly kidding, but I do see a lot of similarities in the evolution of
    the various FormBuilder/Validator modules. That code snipped posted above
    is pretty much exactly how you'd use a Rose::HTML::Form in a TT template
    (plus or minus some method name tweaks).

    -John

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedNov 22, '05 at 1:12p
activeNov 22, '05 at 8:06p
posts8
users6
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase