George_Sherston has asked for the wisdom of the Perl Monks concerning the following question:

Sibling monks - I crave your indulgence - I have two ways to do a thing, neither of which quite hits the spot. Is there a Third Way?

I'm outputting a CGI form via HTML::Template. Sometimes it's a blank form, sometimes it has values filled in (because the user selected them in an earlier session). Now, I have a lot of drop-down (or pop-up if you're a CGI.pm buff) menus. To populate those menus with values using HTML::Template I can't see any alternative to having a series of <TMPL_IF> statements, like:
<select name="MinDuration"> <option value=0<TMPL_IF MINDURATION0> selected</TMPL_IF>> any <option value=1<TMPL_IF MINDURATION1> selected</TMPL_IF>> one +day <option value=2<TMPL_IF MINDURATION2> selected</TMPL_IF>> two +days <option value=3<TMPL_IF MINDURATION3> selected</TMPL_IF>> thre +e days <option value=4<TMPL_IF MINDURATION4> selected</TMPL_IF>> four + days <option value=5<TMPL_IF MINDURATION5> selected</TMPL_IF>> one +week </select>
But that means (AFAIK) that in the hash which I feed to my template I have to have lots ofkeys that don't do anything - i.e. to select "3 days":
$my_template->param( { minduration0 => 0, minduration1 => 0, minduration2 => 0, minduration3 => 1, minduration4 => 0, minduration5 => 0, } );
Plus, this is ugly because there is no direct relationship between the returned value and the value I feed to my template.

The alternative I see is to use CGI.pm to generate the whole menu. Then instead of the html above I'd just have
<TMPL_VAR DATEMENU>
And then in the script I'd have
$my_template->param( { datemenu => popup_menu( -name => 'MinDuration', -values => [0..5], -default => 3, -labels => { 0 => ' any', 1 => ' one day', 2 => ' two days', 3 => ' three days', 4 => ' four days', 5 => ' one week', } ),
But neither of these is quite right. The first is too cludgy in translating from submitted values to initialisation values; the seconde uses all the CGI.pm magic, but it's a two step, and it involves sending large chunks of html to HTML::Template which... feels a bit wrong. Left to my own devices I'd go with method two as the lesser evil, but I wonder if there is a cleaner way - either some clever HTML::Template wheeze, or a different templating system or... TIMTOWTDI???

§ George Sherston

Replies are listed 'Best First'.
Re: SELECT pop-up menus in HTML::Template
by Asim (Hermit) on Jan 17, 2002 at 00:52 UTC

    Yes, a duplicate...Sorry

    I would consider the wonders of the TMPL_LOOP command, and let off the CGI.pm HTML-building bits. One I started using HTML::Template, I decided to simply build my HTML in the standard fashion, and let the Template functions fill in the dynamic data, and the work went much smoother. The Template would be something (very) roughly like (Prototype Template code!):
    <select name="MinDuration"> <TMPL_LOOP NAME="Options"> <option value=<TMPL_VAR NAME="value"><TMPL_IF NAME="value"> selected</ +TMPL_IF>> <TMPL_VAR NAME="text"> </TMPL_LOOP>
    And in the perl code (prototype again):
    $my_template->param( Options => [ {value => '0', text => 'any'}, {value => '1', text => 'one day}, #etc... ] );
    See the HTML::Template documentation for more information on this, naturally.

    ----Asim, known to some as Woodrow.

Re: SELECT pop-up menus in HTML::Template
by gav^ (Curate) on Jan 17, 2002 at 00:55 UTC

    Feels strange replying again, but I thought about it for a bit and using Javascript sucks, so here's a slightly different take on doing it with the template.

    use HTML::Template; my $tmpl = q{ <TMPL_LOOP NAME=OPTIONS> <option value="<TMPL_VAR NAME=VALUE>" <TMPL_VAR NAME=SELECTED> +><TMPL_VAR NAME=TEXT></option> </TMPL_LOOP> }; my @options = (); for (0..5) { push @options, { VALUE => $_, SELECTED => $_ == 3 ? 'selected' : '', TEXT => { 0 => ' any', 1 => ' one day', 2 => ' two days', 3 => ' three days', 4 => ' four days', 5 => ' one week', }->{$_}, }; } my $t = HTML::Template->new(scalarref => \$tmpl); $t->param(OPTIONS => \@options); print $t->output;

    gav^

Re: SELECT pop-up menus in HTML::Template
by gav^ (Curate) on Jan 17, 2002 at 00:24 UTC

    I had the same problem, and came up with a bit of a cludge to fix it. Unfortunatly it uses javascript.

    <script> function cbo_sel(val, cbo) { for (var i = 0; i < cbo.options.length; i++) { if (cbo.options[i].value == val) { cbo.selectedIndex = i; return; } } } </scipt>

    And then in the <body> tag:

    <body onLoad="cbo_sel('<TMPL_VAR NAME=BLAH>', document.forms[0][1])">

    I couldn't think of anything better, I have quite a few combo boxes on the same page. It makes the template and the perl code cleaner but I know it isn't the best solution.

    I'd love to find a workable alternative.

    gav^