http://www.perlmonks.org?node_id=274534

Item Description: Automagically populate HTML forms with CGI parameters

Review Synopsis:

After some discussion with grantm, it was suggested that I take a look at HTML::FillInForm because "it's magic". Having used it now, I agree!

HTML::FillInForm takes the form you give it and automagically populates fields on that form with parameters from a CGI object that you also pass it (read: sticky forms). You may be thinking, "I already can do sticky forms with CGI.pm! Why do I need this?" Templating!

While you can use HTML::FillInForm in most any instance (as a substitute for sticky forms with CGI.pm, for example), I have found it to be most invaluable when working with HTML::Template (I imagine it would provide the same benefits for users of TT or HTML::Mason too). It has drastically cut down the complexity and programming required to redisplay a form to a user with their information filled in.

How does it work? First we create the fill-in-form object:

my $form = new HTML::FillInForm; my $page = $form->fill(scalarref => \$html, fobject => $request);
$html contains the HTML of the form to fill in. $request is a CGI object that contains one or more parameters that you would like to fill in your form with. The call to fill() does the rest. It's that easy! fill() returns the HTML of the filled-in form. So how does this save work? Consider the following sample template:
<form method="post" action=<!-- TMPL_VAR NAME=action --> enctype="appl +ication/x-www-form-urlencoded"> <center> <table> <tr> <td valign="top">Pay by </td> <td valign="top"> <input type="radio" name="searchby" value="Parcel" + checked="checked" />Parcel <input type="radio" name="searchby" value="Name" / +>Name <input type="radio" name="searchby" value="Address +" />Address </td> </tr> <tr> <td>Enter Search Value</td> <td><input type="text" name="searchkey" value=<!-- TMP +L_VAR NAME=DEFAULT --> maxlength="255" length="50" /></td> </tr> </table> <input type="submit" name="action" value="Search" /> <input type="submit" name="action" value="Verify" /> <input type="submit" name=".defaults" value="Defaults" /> </center> <input type="hidden" name=".cgifields" value="searchby" /> </form>
The Perl to populate this looks something like:
$tmpl_form->param( ACTION => "/path/to/my/script.cgi", DEFAULT => $request->param("searchkey"), );
Essentially, I have to create an extra TMPL_VAR for each form field that I would like to fill in. With HTML::FillInForm, we can omit the DEFAULT TMPL_VAR and let fill() handle it for us. Not a big deal when dealing with a text field or two, I realize. But what about those radio buttons? Let's adjust our template to account for those:
<form method="post" action=<!-- TMPL_VAR NAME=action --> enctype="appl +ication/x-www-form-urlencoded"> <center> <table> <tr> <td valign="top">Pay by </td> <td valign="top"> <input type="radio" name="searchby" value="Parcel" + <!-- TMPL_IF NAME=PARCEL -->checked="checked"<!-- /TMPL_IF --> />Par +cel <input type="radio" name="searchby" value="Name" < +!-- TMPL_IF NAME=NAME -->checked="checked"<!-- /TMPL_IF --> />Name <input type="radio" name="searchby" value="Address +" <!-- TMPL_IF NAME=ADDRESS -->checked="checked"<!-- /TMPL_IF --> />A +ddress </td> </tr> <tr> <td>Enter Search Value</td> <td><input type="text" name="searchkey" value=<!-- TMP +L_VAR NAME=DEFAULT --> maxlength="255" length="50" /></td> </tr> </table> <input type="submit" name="action" value="Search" /> <input type="submit" name="action" value="Verify" /> <input type="submit" name=".defaults" value="Defaults" /> </center> <input type="hidden" name=".cgifields" value="searchby" /> </form>
Our Perl transforms into something vastly less elegant:
$tmpl_form->param( ACTION => "/path/to/my/script.cgi", DEFAULT => $request->param("searchkey"), PARCEL => $request->param("searchby") eq "Parcel" ? "true" : "" +, NAME => $request->param("searchby") eq "Name" ? "true" : "" +, ADDRESS => $request->param("searchby") eq "Address" ? "true" : "" +, );
What a lot of work to do when we can simply:
$tmpl_form->param( ACTION => "/path/to/my/script.cgi" ); my $html = $tmpl_form->output; my $form = new HTML::FillInForm; $html = $form->fill(scalarref => \$html, fobject => $request);
and be done with it :) And this is just a simple example. Add more complexity to the form and your Perl will grow more complex to account for it. With HTML::FillInForm, you can add complexity to the above form and not have to add any additional code to handle it.

For sake of brevity, I did not include code to validate or detaint parameters here. It goes without saying that you should always be doing those things when processing user input.

One potential downside (note that I don't have benchmarks to back me up) is that it relies upon HTML::Parser to perform its magic. While there's nothing wrong with that, there may be some overhead associated with creating an HTML::Parser object, especially on a high-traffic site (see this node from Ovid). I would expect this to be a rather moot issue on a site running mod_perl.

All in all, an excellent module, and a worthwhile addition to any Perl programmer's bag-of-tricks.

MrCromeDome