http://qs321.pair.com?node_id=222769

I'm building a CGI application where I need to have forms that retain state between invocations. You know the type: You fill out a bunch of fields on a page and hit submit, and when the validator discovers that some of your responses are impermissible, or you need to back up for whatever reason, you get a form whose form elements are just as you entered them -- no re-typing. The forms may contain items like checkboxes, radio buttons, and multiple-select lists in addition to text fields. I've come up with an approach that works, but I'd love to hear how other monks have approached this problem and see if there's a more elegant solution in the offing.

It's easy enough to build sticky forms if you use the HTML-generation methods/functions in CGI.pm. But I'm a strong proponent of isolating presentation (HTML) from business logic, so I didn't want to create forms by writing a bunch of code. Instead I wanted a way to leverage the templating system I was already using -- HTML::Template.

I thought about using the logical constructs in HTML::Template to try to create sticky form widgets, but in addition to feeling clumsy, that seemed like an inordinate amount of work. I also looked at HTML::StickyForms, but it didn't seem to offer much that isn't already provided by CGI. HTML::FillInForms looked more promising but I wasn't thrilled by the fact that it relies on HTML::Parser, which seems like it would add a lot of overhead on complex pages. (I'm aware that I could be falling into the premature-optimization trap here, but I wanted to at least explore lighter-weight alternatives.)

The solution I eventually tried was to build a bridge between HTML::Template variables and the sticky form-generation capabilities of CGI. I defined a way to denote form elements using HTML::Template variables. Then my sub that instantiates and populates the template looks for all the template variable names that match a certain pattern, and calls the appropriate CGI element generator to set the value for that template variable. So my form templates now have sections that look something like this:

Your name: <TMPL_VAR NAME="FORM_TEXTFIELD_NAME"><br> Your favorite pastimes: <TMPL_VAR NAME="FORM_LIST_PASTIMES">
The basic attributes (field type and name) of the form elements are encoded in the name of the template variable. Field-specific parameters are stored in a hash keyed on the field name, which both allows me to generate items programmatically and avoids requiring some way to encode this information in the template variable name. It also means that if I'm careful about my field naming, multiple templates could refer to a field that will always have the same attributes (for example, a username might always be maxlength=15, size=15, regardless of which form it's on).

This all seems to work fine. But I'd love to get feedback from the folks in this community and also to hear of any other approaches that monks have found fruitful.

        $perlmonks{seattlejohn} = 'John Clyman';