perlmeditation
dws
<p>
When you're using HTML::Template and want to put a table into a page, you have two options: You can embed loop logic in the template, or you can inject a table constructed elsewhere into the template. If you favor reuse, you're going to lean towards injection. But that doesn't mean you can't use templates for both parts. Here's a variation that does both, in a reusable way.
</p>
<p>
A simple embedded table looks like
</p>
<code>
... stuff ...
<table>
<TMPL_LOOP rows>
<tr>
<TMPL_LOOP columns>
<td><TMPL_VAR ESCAPE=HTML value></td>
</TMPL_LOOP>
</tr>
</TMPL_LOOP>
</table>
... more stuff ...
</code>
<p>
and the code to expand it looks like
</p>
<code>
my $template = HTML::Template->new(rows => ...);
print $template->output;
</code>
<p>
You can isolate part of the above into a separate template, and pull it in to the main template via
</p>
<code>
... stuff ...
<TMPL_INCLUDE NAME="table.tmpl">
... more stuff ...
</code>
<p>
This expands the included template in-line, with no visible difference to the calling program, though you do get the benefit of having a reusable table template. But you can do better, as we'll see below.
</p>
<p>
When injecting a table, the template looks like
</p>
<code>
... stuff ...
<TMPL_VAR ESCAPE=0 table>
... more stuff ...
</code>
<p>
You're then on the hook for providing a chunk of HTML to supply as the template parameter <code>table.</code> You can construct the HTML from code, from a heredoc, by using CGI.pm tag support, or by some other means. Whichever way you go, you'll end up doing something like
</p>
<code>
my $template = HTML::Template->new(filename => 'bigpage.tmpl');
my $tableHTML = tableHTML(...);
$template->param(table => $tableHTML);
print $template->output;
</code>
<p>
A possibly non-obvious "other means" is to produce the table HTML by using a separate <code>HTML::Template</code> instance that uses its own template for the table part. This looks like
</p>
<code>
sub tableHTML {
my %table_data = @_;
my $template = HTML::Template->new(filename => 'table.tmpl');
$template->param(%table_data);
return $template->output;
}
</code>
<p>
You now have the basis for a reusable component that you can pull out any time you need to embed tables in a template. Variations include passing a query into the component, which then extracts data from some data source. This technique also extends nicely to other types of components.
</p>