Moritz Sinn > HTML-FormEngine > HTML::FormEngine

Download:
HTML-FormEngine-1.01.tar.gz

Dependencies

Annotate this POD

View/Report Bugs
Module Version: 1.01   Source  

NAME ^

HTML::FormEngine - create,validate and control html/xhtml forms

DEPENDENCIES ^

Perl Version

        5.004

Standard Modules

        Carp

Nonstandard Modules

        Clone 0.13
        Hash::Merge 0.07
        Locale::gettext 1.01
        Date::Pcalc 1.2
        Digest::MD5 2.24
        HTML::Entities 1.27

SYNOPSIS ^

Example Code

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use HTML::FormEngine;
    #use POSIX; # for setlocale
    #setlocale(LC_MESSAGES, 'german'); # for german error messages

    my $q = new CGI;
    print $q->header;

    my $Form = HTML::FormEngine->new(scalar $q->Vars);
    my @form = (
                {
                  templ => 'select',
                  NAME => 'Salutation',
                  OPTION => [[['mr.','mrs.']]],
                },
                {
                  templ => 'hidden_no_title',
                  NAME => 'test123',
                  VALUE => 'test',
                },
                {
                 SIZE => 10,
                 MAXLEN => 20,
                 PREFIX => [[' ', ' / ']],
                 NAME => 'name',
                 TITLE => 'For- / Surname ',
                 ERROR_IN => 'not_null'
                },
                {
                  MAXLEN => 30,
                  NAME => 'Email',
                  ERROR => ['not_null', ['rfc822'], ['match', 'matched net!']] # rfc822 defines the email address standard
                },
                {
                 templ => 'radio',
                 TITLE => 'Subscribe to newsletter?',
                 NAME => 'newsletter',
                 OPT_VAL => [[1, 2, 3]],
                 OPTION => [['Yes', 'No', 'Perhaps']],
                 VALUE => 1
                },
                {
                 templ => 'check',
                 OPTION => 'I agree to the terms of condition!',
                 NAME => "agree",
                 TITLE => '',
                 ERROR => sub{ return("you've to agree!") if(! shift); }
                }
    );

    $Form->set_seperate(1);
    $Form->conf(\@form);
    $Form->make();

    print $q->start_html('FormEngine example: Registration');
    if($Form->ok){
      $Form->clear();   
      print "<center>You've successfully subscribed!</center><br>";
    }
    print $Form->get,
          $q->end_html;

Example Output

This output is produced by FormEngine when using the example code and no data was submitted:

    <form action="/cgi-bin/formengine/registration.cgi" method="post" name="FormEngine" accept="*" enctype="application/x-www-form-urlencoded" target="_self" id="FormEngine" >
    <table border=0 cellspacing=1 cellpadding=1 align="center" >
    <tr >
       <td valign="top" align="left" ><label for="Salutation" accesskey="">Salutation</label><span ></span></td>
       <td >
          <table border=0 cellspacing=0 cellpadding=0 >
            <tr >

              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>
                    <td >

         <select size="" name="Salutation" id="Salutation"  >
            <option value="mr." label="mr."  >mr.</option> 
            <option value="mrs." label="mrs."  >mrs.</option> 
         </select>

                    </td>
                    <td > &nbsp; </td>
                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
            </tr>
          </table>

    </td>
       <td align="left" valign="bottom" style="color:#FF0000"></td><input type="hidden" name="Salutation" value="f29e202fda026b18561398f7879cdf37" />
    </tr>
    <tr ></tr>
    <tr >
       <td valign="top" align="left" ><label for="name" accesskey="">For- / Surname </label><span ></span></td>
       <td >
          <table border=0 cellspacing=0 cellpadding=0 >
            <tr >
              <td valign="top" >

                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" >&nbsp;</td>
                    <td >
                      <input type="text" value="" name="name" id="name" maxlength="20" size="10"  />
                    </td>
                    <td > &nbsp; </td>
                  </tr>

                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" >&nbsp;/&nbsp;</td>
                    <td >

                      <input type="text" value="" name="name" id="name" maxlength="20" size="10"  />
                    </td>
                    <td > &nbsp; </td>
                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
            </tr>

          </table>
    </td>
       <td align="left" valign="bottom" style="color:#FF0000"></td><input type="hidden" name="name" value="f29e202fda026b18561398f7879cdf37" />
    </tr>
    <tr >
       <td valign="top" align="left" ><label for="Email" accesskey="">Email</label><span ></span></td>
       <td >
          <table border=0 cellspacing=0 cellpadding=0 >
            <tr >
              <td valign="top" >

                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>
                    <td >
                      <input type="text" value="" name="Email" id="Email" maxlength="30" size="20"  />
                    </td>
                    <td > &nbsp; </td>

                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
            </tr>
          </table>
    </td>
       <td align="left" valign="bottom" style="color:#FF0000"></td><input type="hidden" name="Email" value="f29e202fda026b18561398f7879cdf37" />
    </tr>
    <tr >

       <td valign="top" align="left" ><label for="newsletter" accesskey="">Subscribe to newsletter?</label><span ></span></td>
       <td >
          <table border=0 cellspacing=0 cellpadding=0 >
            <tr >
              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>

                    <td >
                      <input type="radio" value="1" name="newsletter" id="newsletter" checked />Yes
                    </td>
                    <td > &nbsp; </td>
                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>

              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>
                    <td >
                      <input type="radio" value="2" name="newsletter" id="newsletter"  />No
                    </td>
                    <td > &nbsp; </td>

                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>

                    <td >
                      <input type="radio" value="3" name="newsletter" id="newsletter"  />Perhaps
                    </td>
                    <td > &nbsp; </td>
                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>

            </tr>
          </table>
    </td>
       <td align="left" valign="bottom" style="color:#FF0000"></td><input type="hidden" name="newsletter" value="f29e202fda026b18561398f7879cdf37" />
    </tr>
    <tr >
       <td valign="top" align="left" ></td>
       <td >
          <table border=0 cellspacing=0 cellpadding=0 >
            <tr >

              <td valign="top" >
                <table border=0 cellspacing=0 cellpadding=0 >
                  <tr >
                    <td align="" valign="" > &nbsp; </td>
                    <td >
                      <input type="checkbox" value="I agree to the terms of condition!" name="agree" id="agree"  />I agree to the terms of condition!
                    </td>
                    <td > &nbsp; </td>

                  </tr>
                  <tr ><td ></td><td style="color:#FF0000"></td></tr>
                </table>
              </td>
            </tr>
          </table>
    </td>
       <td align="left" valign="bottom" style="color:#FF0000"></td><input type="hidden" name="agree" value="f29e202fda026b18561398f7879cdf37" />
    </tr>
    <tr >

       <td align="right" colspan=3 >
          <input type="submit" value="Ok" name="FormEngine" />
       </td>
    </tr>
    </table>

    </form>

DESCRIPTION ^

FormEngine.pm is a Perl 5 object class which provides an api for managing html/xhtml forms. FormEngine has its own, very flexible template system for defining form skins. A default skin and a more flexible one is provided. This should be sufficent in most cases, but extending the skins or making your own isn't difficult (please send them to me!).

FormEngine also provides a set of functions for checking the form input, it is very easy to define your own check methods or to adapt the given.

gettext is used for internationalization (e.g. error messages). So use setlocale(LC_MESSAGES, 'german') if you want to have german error messages, butten lables and so on (there isn't support for any other language yet, but it shouldn't be difficult to translate the .po file, don't hesitate!).

Another usefull feature is the confirm method which forces the user to read through his input once again before submitting it.

FormEngine is designed to make extension writing an easy task!

OVERVIEW ^

Start with calling the new method, it will return an FormEngine object. As argument you should pass a reference to a hash of input values (calling set_input is also possible, environments like mod_perl or CGI.pm offer already a hash of input values, see set_input for more). Now define an array which contains the form configuration and pass a reference to conf. Then call make, this will generate the html code. Next you can use ok to check if the form was submitted and all input values are correct. If this is the case, you can e.g. display a success message and call get_input(fieldname) for getting the value of a certain field and e.g. write it in a database. Else you should call get (which will return the html form code) or print which will directly print the form.

If you want the form to be always displayed, you can use clear to empty it (resp. display the defaults) when the transmission was successfull.

USING FORMENGINE ^

The easiest way to define your form is to create an array of hash references:

    my @form = (
                {
                  templ => 'select',
                  NAME => 'Salutation',
                  OPTION => [[['mr.','mrs.']]],
                },
                {
                  templ => 'hidden_no_title',
                  NAME => 'test123',
                  VALUE => 'test',
                },
                {
                 SIZE => 10,
                 MAXLEN => 20,
                 PREFIX => [['&nbsp;', '&nbsp;/&nbsp;']],
                 NAME => 'name',
                 TITLE => 'For- / Surname ',
                 ERROR_IN => 'not_null'
                },
                {
                  MAXLEN => 30,
                  NAME => 'Email',
                  ERROR => ['not_null', ['rfc822'], ['match', 'matched net!']] # rfc822 defines the email address standard
                },
                {
                 templ => 'radio',
                 TITLE => 'Subscribe to newsletter?',
                 NAME => 'newsletter',
                 OPT_VAL => [[1, 2, 3]],
                 OPTION => [['Yes', 'No', 'Perhaps']],
                 VALUE => 1
                },
                {
                 templ => 'check',
                 OPTION => 'I agree to the terms of condition!',
                 NAME => "agree",
                 TITLE => '',
                 ERROR => sub{ return("you've to agree!") if(! shift); }
                }
    );

This was taken out of the example above. The templ key defines the field type (resp. template), the capital written keys are explained below. If templ is not defined, it is expected to be text.

Then pass a reference to that array to the conf method like this:

       $Form->conf(\@form);

Another possibility is to define a hash of hash references and pass a reference on that to conf. This is seldom needed, but has the advantage that you can define low level variables:

       my %form = (
            METHOD => 'get',
            FORMNAME => 'myform',
            SUBMIT => 'Yea! I want that!',
            'sub' => [ 
                        # Here you place your form definition (see above)
                     ] 
       );

       $Form->conf(\%form);

The meaning of the keys is explained below. You can call set_main_vars for setting low level (main) variables as well, the only difference is that the variables set through "set_main_vars ( HASHREF )" are persistend, that means even if you call the "conf ( FORMCONF )" method again they're still set if not overwritten.

The Default Skin (FormEngine)

If you want to use the same fieldname several times (e.g. for a group of checkboxes or for two textfields like name and forename), you have to call set_seperate and pass 1 (for true). See set_seperate for more.

The following templates are known by the default skin:

The following templates are also known by the default skin but perhaps a bit more difficult to understand and not so often used:

These fields are normally only used automatically for generating the confirmation form but could be that they're also for some individual usage:

If you want to nest templates resp. place a template in another template you have to call it with a leading '_' (underscore). So use _text instead of text and so on.

Add _notitle to the templates name if you don't want to have a title, add _noerror if you don't want to check for errors, add _notitle_noerror if you don't want both and simply add a 2 if you want the error messages to stand under the field and not next to it. Read and run the examples for more information.

NOTE: All information given here about templates and variables is only valid for the default skin and for SkinComplex. Other skins should bring their own documentation.

Variables

Note that if you don't use the default skin, things might be diffrent. But mostly only the layout changes. A skin which doesn't fit to the following conventiones should have its own documentation.

These Variables are always available:

These variables are available for the text template only:

These variables are available for selection templates (radio, select, check and all similar ones) only:

These variables are available for the optgroup template and all similar ones:

These variables are available for the textarea template only:

These variables are available for the button template only:

These variables are so called main variables, they can be set by using the hash notation (see "USING FORMENGINE") or by calling "set_main_vars ( HASHREF )":

Note: only NAME must be set, all other variables are optional.

Please also run the example scripts and read their code (they're very short), it'll help you a lot understanding how to use FormEngine.

To really understand the skin system, how it works and what possibilites there are you'll have to read the documentation of and the code in the following files: Skin.pm, SkinComplex.pm, SkinClassic.pm, SkinClassicConfirm.pm. These files are related to each other in exactly this order, there's also SkinClassicConfirm.pm which inherits everythings from SkinComplex but besides that it looks the same like SkinClassicConfirm.pm.

There are many more variables and possibilites than documented above, you have to read the template definitions in the skin packages to know more!

Methods For Creating Forms

new ([ HASHREF ])

This method is the constructor. It returns an FormEngine object. You should pass the form input in a hash reference to it, but you can use "set_input ( HASHREF )" as well.

set_input ( HASHREF )

You have to pass a reference to a hash with input values. You can pass this hash reference to the constructor (new) as well, then you don't need this function. If you use mod_perl you can get this reference by calling 'scalar $m->request_args'. If you use CGI.pm you get it by calling 'scalar $q->Vars'.

conf ( FORMCONF )

You have to pass the configuration of your form as array or hash reference (see "USING FORMENGINE").

set_seperate ( BOOLEAN )

You've to pass true in case you want to use the same field name in diffrent template calls. Its turned off by default because you won't be able to set field values with java-script once it is enabled (which doesn't matter in most cases).

set_main_vars ( HASHREF )

You can use this method for setting the values of the main template variables (e.g. SUBMIT). Another possibility to do that is using the hash notation when configuring the form (see "USING FORMENGINE"). The diffrence is that the object saves the settings made through this method so that they're automatically reset when calling the "conf ( FORMCONF )" method again. If you set the variables directly throught the hash notation they're not persistent.

This method doesn't overwrite all settings which where probably already made before, it only overwrites the variables which are defined in the given HASH! So you can call this method several times to complete your configuration or overwrite certain values.

To delete main variable settings use "del_main_vars ( ARRAY )".

del_main_vars ( ARRAY )

Use this method to unset so called main variables. They're not only removed out of the form configuration but also out of the cache so that you can get rid of settings that you once made with "set_main_vars ( HASHREF )" but which you don't want anymore, in fact this is the real purpose of this method. Just pass the names of the variables which should not be defined anymore.

clear ( )

If the form was submitted, this method simply calls "set_use_input ( VALUE )" and "set_error_chk ( VALUE )". It sets both to false. If make was already called, it calls it again, so that no user input is shown and no error checking is done. Use it to reset the form.

set_error_chk ( VALUE )

Sets whether the error handler should be called or not. Default is true (1).

set_use_input ( VALUE )

Sets whether the given input should be displayed in the form fields or not. Default is true (1).

make ( )

Creates the html/xhtml output, but doesn't return it (see "get ( )" and "print ( )"). Every method call which influences this output must be called before calling make!

print ( )

Sends the html/xhtml output directly to STDOUT. "make ( )" must be called first!

get ( )

Returns the html/xhtml form code in a string. "make ( )" must be called first!

ok ( )

Returns true (1) if the form was submitted and no errors were found! Else it returns false (0).

This method simply calls "is_submitted ( )" and "get_error_count ( )" but also checks whether a confirmation was canceled ("confirmation_canceled ( )"). So normally you'll use this method instead of calling all 3 functions, especially if you deal with the confirmation feature of FormEngine (see "confirm ( [CONFIRMMSG] )").

"make ( )" must be called before calling this method!

get_error_count ( )

Returns the count of errors which where found by the error handler. "make ( )" must be called first!

is_submitted ( )

Returns true (1) if the form was submitted, false (0) if not.

errors ( )

Returns true if the form was submitted and errors where found.

confirmation_canceled ( )

Returns true if the user pressed Cancel when he was asked to confirm the given input.

get_input ( FIELDNAME )

Returns the input value of the corresponding field. If it has only one value a scalar, if it has several values an array is returned. If set_seperate was called with 1 (true) it packs the values which belong together into subarrays.

confirm ( [CONFIRMMSG] )

Calling this method will print the users input data and ask him to click 'Ok' or 'Cancel'. 'Ok' will submit the data once again and then is_confirmed will return true (1). 'Cancel' will display the form, so that the user can change the data.

By default the message defined for CONFIRMSG in Skin.pm will be displayed, but you can also pass your own text.

is_confirmed ( )

This method returns true (1) when the form input was affirmed by the user (see "confirm ( [CONFIRMSG] )").

Methods For Configuring FormEngine

set_skin_obj ( OBJECT )

If you want to use an alternative skin, call this method. You've to pass a valid skin object.

An example: $form-set_skin_obj(new HTML::FormEngine::SkinComplex)>.

The default skin object is an instance of HTML::FormEngine::SkinClassic.

For more information please read HTML::FormEngine::Skin.

Of course this method has to be called before calling "make ( )".

get_skin_obj ( )

Returns the currently used skin object.

Debug Methods

set_debug ( DEBUGLEVEL )

Sets the debug level. The higher the value the more output is printed (to STDERR).

get_method ( )

Returns the value of mains METHOD variable (should be get or post).

get_formname ( )

Returns the value of mains FORMNAME variable. If you have several FormEngine forms on one page, these forms mustn't have the same FORMNAME value! You can set it with "set_main_vars ( HASHREF )".

get_conf ( )

Returns a reference to a hash with the current form configuration. Changing this hash doesn't influence the configuration, because it is just a copy.

print_conf ( HASHREF )

Prints the given form configuration to STDERR.

Special Features

nesting templates

There are two ways how you can nest templates. The first one is to put a handler call in the template definition. This is a less flexible solution, but it might be very usefull. See HTML::FormEngine::Skin for more information.

The second and flexible way is, to assign a handler call to a template variable (see HTML::FormEngine::Skin for more information about handler calls). A good example for this way is hobbies.cgi. There you have a option called other and an input field to put in the name of this alternative hobby. When you look at the form definition below, you see that the value of the OPTION variable of this option is simply <&_text&>, this is a handler call. So the handler is called and its return value (in this case the processed _text template) is assigned to the variable.

The form definition of hobbies.cgi:

    my @form = (
            {
              templ => 'check',
              NAME  => 'hobbie',
              TITLE => 'Hobbies',
              OPTION => [['Parachute Jumping', 'Playing Video Games'], ['Doing Nothing', 'Soak'], ['Head Banging', 'Cat Hunting'], "Don't Know", '<&_text&>'],
              OPT_VAL => [[1,2], [3,4], [5,6], 7, 8],
              VALUE => [1,2,7],
             'sub' => {'_text' => {'NAME' => 'Other', 'VALUE' => '', ERROR => ''}},
              ERROR_IN => sub{if(shift eq 4) { return "That's not a faithfull hobby!" }}
            }
    );

If you have a closer look at the form definition above, you'll recognize that there is a key called 'sub'. With help of this key you can define the variables of the nested templates. If the nested templates don't use the same variable names as their parents, you don't need that, because then you can assign these variables on the same level with the parents template variables.

EXTENDING FORMENGINE ^

Modify A Skin

To set the current skin, use the method "set_skin_obj ( OBJECT )". To Modify it you should have a look at HTML::FormEngine::Skin.

Extending Or Writing A Skin

Have a look at HTML::FormEngine::Skin for this task and especially read its source code and the code and documentation of the other skin packages. You can easily change the layout by copying the skin hash, fitting the html code to your needs and then using "set_skin_obj ( OBJECT )" to overwrite the default. Please send me your skins.

Write A Handler

Read HTML::FormEngine::Handler. Also read HTML::FormEngine::Skin on how to make the handler available. To make it persistent see "Extending Or Writing A Skin".

Write A Check Routine

The design of a check routine is explained in HTML::FormEngine::Checks. You can easily refer to it by reference or even define it in line as an anonymous function (see the ERROR template variable). If your new written routine is of general usage, you should make it part of FormEngine by placing it in Checks.pm and refering to it from Skin.pm. For more read HTML::FormEngine::Skin. Please send me your check methods!

MORE INFORMATION ^

Have a look at ...

BUGS ^

Please use http://rt.cpan.org/NoAuth/Bugs.html?Dist=HTML-FormEngine to inform you about reported bugs and to report bugs.

If it doesn't work feel free to email directly to moritz@freesources.org.

Thanks!

AUTHOR ^

(c) 2003-2004, Moritz Sinn. This module is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (see http://www.gnu.org/licenses/gpl.txt) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

    This module is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

I am always interested in knowing how my work helps others, so if you put this module to use in any of your own code please send me the URL. If you make modifications to the module because it doesn't work the way you need, please send me a copy so that I can roll desirable changes into the main release.

Please use http://rt.cpan.org/NoAuth/Bugs.html?Dist=HTML-FormEngine for comments, suggestions and bug reports. If it doesn't work feel free to mail to moritz@freesources.org.

CREDITS ^

Special thanks go to Darren Duncan. His HTML::FormTemplate module gave me a good example how to write a documentation. There are several similarities between HTML::FormEngine and HTML::FormTemplate, we both came to an related API design, the internal processes are completly diffrent. It wasn't my purpose to have these api design decisions in common with HTML::FormTemplate. When i wrote the php version of HTML::FormEngine, i didn't know anything about HTML::FormTemplate. Later i just ported this php class to perl. I think we both came to an likewise API because its just the most obvious solution.

Features which FormEngine has and FormTemplate hasn't:

Features which FormTemplate has and FormEngine hasn't:

This list will be filled in later.

(I asked the author to send me some notes, he told me he'll do so at opportunity.)

SEE ALSO ^

HTML::FormTemplate by Darren Duncan

syntax highlighting: