note
dkubb
<p>What you want to do is possible, but requires
you to use an underused feature in [cpan://HTML::Template]
called <b>loop_context_vars</b>. Enabling it in the
<code>new()</code> constructor will allow you to use the
loop context variables: <code>__FIRST__</code>, <code>__LAST__</code>, <code>__INNER__</code>, <code>__ODD__</code>
inside your <code>TMPL_IF</code> or <code>TMPL_UNLESS</code> tags. To see what I
mean, check out the template example at the bottom of this post.</p>
<p>In particular, we care about the <code>__ODD__</code> variable, which
will be set to true on the odd numbered passes. By testing this variable,
we can print either the <code><tr></code> or <code></tr></code>
tags when appropriate. Consider the following code:</p>
<code>#!/usr/bin/perl -w
use strict;
use HTML::Template;
my @scores = (
{ name => 'name1', score => 4 },
{ name => 'name2', score => 2 },
{ name => 'name3', score => 3 },
);
my $template = HTML::Template->new(
filename => 'scores.tmpl',
loop_context_vars => 1,
);
$template->param(scores => \@scores);
print $template->output;</code>
<p>Which loads a template that contains the following
text: </p>
<code>
<table>
<TMPL_LOOP NAME='scores'>
<TMPL_IF NAME='__ODD__'>
<tr>
</TMPL_IF>
<td><TMPL_VAR NAME='name'></td><td><TMPL_VAR NAME='score'></td>
<TMPL_UNLESS NAME='__ODD__'>
</tr>
</TMPL_UNLESS>
</TMPL_LOOP>
</table>
</code>
<p>This will iterate over the <code>@scores</code> and
print them in two columns in the table. There is only one
drawback to this approach, if the <code>@scores</code> has
an odd number of elements, the final <code></tr></code>
will not be printed. This can either be solved by pushing
an empty element onto the array, or creative
use of the <code>__LAST__</code> and <code>__ODD__</code>
variables together. I personally prefer the latter and
try to offload presentation logic off to the
template, rather than pollute the code with special
exceptions.</p>
93641
93641