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

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.

A simple embedded table looks like

... stuff ... <table> <TMPL_LOOP rows> <tr> <TMPL_LOOP columns> <td><TMPL_VAR ESCAPE=HTML value></td> </TMPL_LOOP> </tr> </TMPL_LOOP> </table> ... more stuff ...

and the code to expand it looks like

my $template = HTML::Template->new(rows => ...); print $template->output;

You can isolate part of the above into a separate template, and pull it in to the main template via

... stuff ... <TMPL_INCLUDE NAME="table.tmpl"> ... more stuff ...

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.

When injecting a table, the template looks like

... stuff ... <TMPL_VAR ESCAPE=0 table> ... more stuff ...

You're then on the hook for providing a chunk of HTML to supply as the template parameter table. 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

my $template = HTML::Template->new(filename => 'bigpage.tmpl'); my $tableHTML = tableHTML(...); $template->param(table => $tableHTML); print $template->output;

A possibly non-obvious "other means" is to produce the table HTML by using a separate HTML::Template instance that uses its own template for the table part. This looks like

sub tableHTML { my %table_data = @_; my $template = HTML::Template->new(filename => 'table.tmpl'); $template->param(%table_data); return $template->output; }

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.