[html-formfu] multi-page forms

Carl Franks fireartist at gmail.com
Tue Jan 29 16:15:35 GMT 2008


I've added support for multi-page / multi-stage forms.

The main aim of the approach I've taken is to remove the need for
server-side sessions to store the intermediary data.

Data from previous pages is encrypted and stored in a single hidden field.
Having the data encrypted means you don't have to worry about
validating it all over again, as you can be sure the user hasn't
changed it.

Catalyst-Controller-HTML-FormFu has been updated to provide new
multiform-specific actions. MultiFormConfig is comparable to the older
FormConfig action. e.g.

    sub homepage : Path('') : MultiForm {
        my ( $self, $c ) = @_;
    }

will essentially do:

    my $multiform = HTML::FormFu::MultiForm->new;

    $multiform->load_config_file('root/forms/homepage.yml');

    $c->stash->{multiform} = $multiform;

Note that it's creating a HTML::FormFu::MultiForm object, instead of a
HTML::FormFu object.

To use the multiform in your templates, you just need to do:
    [% multiform%]
and it'll do the right thing (tm).

To handle the multiform in your code, you probably just need to do:

sub foo : Path('foo') : MultiForm {
    my ( $self, $c ) = @_;

    my $multi = $c->stash->{multiform};

    if ( $multi->complete ) {
        my $params = $multi->current_form->params;
        # do something with params
    }

}

By default, params() will include all the input from previous forms.
If you don't want that, and would rather handle each form as it's
submitted, set combine_params() to false.
You can retrieve the current form with $multi->current_form;
and the current form number with $multi->current_form_number;
(note that it counts up from 1, not zero!)

An example of a suitable multiform config file is:

    ---
    auto_fieldset: 1

    crypt_args:
      -key: 'my secret'

    forms:
      # form 1
      -
        elements:
          - name: foo
            constraints: [ Required ]

          - type: Submit
            name: submit

      # form 2
      -
        indicator: bar

        elements:
          - name: bar
            constraints: [ Required ]

          - type: Submit
            name: submit

'forms' takes an arrayref, with each item comprising a complete form.

Notice that I set 'auto_fieldset' at the multiform-level. This causes
auto_fieldset to be passed to every form as it's created.
Take note though, that not all form-methods are supported by a
multiform. In particular, you can't set elements(), constraints(),
etc. on a multiform - these need to be set on each individual form.

You must set crypt_args->{-key} yourself, otherwise it'll die.
crypt_args({}) is passed directly to Crypt::CBC->new, so can contain
any args that'll accept.
In particular, you can change the default encryption from DES to something else:

    crypt_args:
      -key: 'my key',
      -cipher: 'Blowfish'

You also don't need to manually add the hidden-field for the encrypted
data yourself.
If you want to add the hidden-field yourself (for example, if you're
not using auto_fieldset, and you're worried about valid markup), the
docs will explain how to - once they're written ;)

I've been playing with this in a test app and am fairly happy with it,
so hopefully the API won't need to change; but the usual caveats
apply.

Cheers,
Carl



More information about the HTML-FormFu mailing list