PerForm is a large and complex taglib for AxKit XSP that facilitates creating
large and complex HTML, WML, or other types of data-entry forms. PerForm tends to
make life easier for you if your form data is coming from different data sources,
such as DBI, or even XML.

PerForm works as an XSP taglib, meaning you simply add some custom XML tags to
your XSP page, and PerForm does the rest. Well, almost... PerForm works mainly
by callbacks, as you will see below.

Now it is important to bear in mind that this is just the form, and alone it is
fairly useless. You also need to add callbacks. You'll notice with each of these
callbacks you recieve a $ctxt object. This is simply an empty hash-ref that
you can use in the callbacks to maintain state. Actually ``empty'' is an
exhageration - it contains two entries always: Form and Apache. ``Form'' is
a simply a hashref of the entries in the form. So for example, the firstname
below is in $ctxt-{Form}{firstname}>. ``Apache'' is the $r apache request
object for the current request.

Now these methods need to be global to your XSP page, rather than ``closures'' within
the XSP page's main handler routine. How do you do that? Well it's simple. Just put
them within a <xsp:logic> section before any user defined tags. For example, if your
XSP page happens to use XHTML as it's basic format (something I do a lot), your page
might be constructed as follows (namespace declarations omitted for brevity):

In PerForm, all forms submit back to themselves. This allows us to implement the callback
system. Of course with most forms, you want to go somewhere else once you've processed
the form. So for this, we issue redirects once the form has been processed. This has the
advantage that you can't hit reload by accident and have the form re-submitted.

To define where you go on hitting submit, you can either return set the goto attribute
on the submit or cancel button, or implement a callback and return a URI to redirect to.

Each of the form callbacks is passed a context object. This is a hashref you are allowed
to use to maintain state between your callbacks. There is a new context object created
for every form on your XSP page. There are two entries filled in automatically into
the hashref for you:

This is actually an Apache::Table object, so it looks and works just like an ordinary
hashref, and contains the values submitted from the form, or is perhaps empty if the
form hasn't been submitted yet. It may also contain any parameters passed in the
querystring. For multi-value parameters, they can be accessed via Apache::Table's
get, add and set methods. See the Apache::Table manpage.

The Apache entry is the apache request object for the current request. You can use
this, for example, to get the current URI, or to get something out of dir_config,
or perhaps to send a header. See the Apache manpage.

To add an entry to the context object, simply use it as a hashref:

$ctxt->{my_key} = $my_value;

And you can later get at that in another callback via $ctxt-{my_key}>.

Sometimes you need to display a list of items in your form where the
number of items is not known until runtime. Use arrayed form elements to trigger
the same callback for each item in the list. When setting up each element, use
an index to identify each member of the list. The callbacks will be passed the
index as a parameter. e.g.

This example produces a list of items with a 'Buy me' button next to each one. Each
button has an index that corresponds an array index of an item in the shopping list.
When one of the submit buttons is pressed, the submit_SubmitBuy callback will be
triggered (as part of the submission procedure) and the browser will redirect to a page
that handles the purchase of the associated item.

NOTE: arrays not supported for multi-select, single-select or file-upload elements.

The following documentation uses the prefix f: for all PerForm tags. This assumes you
have a namespace declaration xmlns:f="http://axkit.org/NS/xsp/perform/v1" in your
XSP file.

Please note that for all of the widget tags, PerForm uses TaglibHelper. This has the
advantage that you can define attributes either as XML attributes in the tag, or
as child tags in the PerForm namespace. So:

<f:textfield name="foo" default="bar"/>

Is exactly equivalent to:

<f:textfield name="foo">
<f:default>bar</f:default>
</f:textfield>

The advantage of this is that child tags can get their content from other XSP tags.

This tag has to be around the main form components. It does not have to have any ACTION
or METHOD attributes, as that is all sorted out internally. Note that you can have as
many f:form tags on a page as you want, but it probably doesn't make sense to nest them.

If you do not wish to implement the callback below, you can set the goto
attribute to a URI to redirect to when the user hits the button. Normally
you won't use this unless you happen to not want to save the form values
in any way.

A cancel button. This is similar to the submit button, but instead of being used
to save the form values (or ``do something'' with them), should be used to cancel
the use of this particular form and go somewhere else. The most common use of this
is to simply set the goto attribute to redirect to another page.

Implement this method to validate the contents of the textfield. If the value is valid,
you don't need to do anything. However if it invalid, throw an exception with the reason
why it is invalid. Example:

Validate the uploaded file. This is also actually the place where you would save the
file to disk somewhere, by reading from $fh and writing to somewhere else, or using
File::Copy to do that for you. It is much harder to access the file from the submit
callback.

If the file is somehow invalid, throw an exception with the text of why it is invalid.

A hidden form field, for storing persistent information across submits.

PerForm hidden fields are quite useful because they are self validating against
modification between submits, so if a malicious user tries to change the value by
editing the querystring or changing the form value somehow, the execution of your
script will die with an exception.

Attributes:

name (mandatory)

The name of the hidden field

value

The value stored in the hidden field

index

Use this to identify the array index when using arrayed form elements.

Set this to ``yes'' or ``1'' to have the textarea wrap the text automatically. Set to
``no'' or leave blank to not wrap. Default is to not wrap.

default

The default text to put in the textarea.

index

Use this to identify the array index when using arrayed form elements.

Callbacks:

load_<name> ( $ctxt, $default, $current, $index )

Load a new value into the widget. Return the string you want to appear in the box.

validate_<name> ( $ctxt, $value, $index )

Validate the contents of the textarea. If the contents are somehow invalid, throw
an exception in your code with the string of the error. One use for this might be
validating a forums posting edit box against a small DTD of HTML-like elements. You can
use XML::LibXML to do this, like this: