Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Nested HTML::Template usage

by skx (Parson)
on Aug 28, 2014 at 07:45 UTC ( #1098839=perlquestion: print w/replies, xml ) Need Help??

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

I've got a fairly complex web application which I've almost completely ported from a series of static cgi scripts to using CGI::Application.

The one outstanding task I've yet to cover is how to handle nested HTML::Template files.

In my application I have a global "layout" template, as well as run-mode-specific templates. We could pretend that the layout would look like this, although in truth there is more divitus:

  <head> <title> <!-- tmpl_var name='title' --></title>
     <div id="content">
       <!-- tmpl_include name='###' -->

The magic here is obviously the insertion of a second template, the run-mode-specific page template, which is carried out dynamically.

HTML::Template doesn't allow loading dynamic include-files so I've had to be sneaky - which is often a sign I'm going down a bad route:

sub mk_include_filter
    my $page = shift;
    return sub {
        my $text_ref = shift;
        $$text_ref =~ s/###/$page/g;

sub load_page_layout
    my( $self, $page, %options ) = ( @_ );

    my $layout = "../templates/layouts/default.template";
    my $l = HTML::Template->new( filename => $layout,
                                 filter => mk_include_filter($page) );

   # ...
   return ($l);

This allows me to run code such as:

my $template = $self->load_page_layout( "about.tmpl" );

The return value is essentially the union of the layout-template and the page-template, and allows values to be set which are defined in either:

$template->param( title => "The title, as defined in the layout",
                  page_specific => "A page-specific value" );

All this works, and works well, but I wonder if there is a better approach to handling dynamic sub-templates, or similar?

Specifically my problem is that I cannot use this approach and migrate to HTML::Template::Compiled because the filter doesn't work as expected. Pages return completely wrong values..

(Edit: The obvious solution is to duplicate the global-layout into each page, if possible I'd like to avoid that as it makes updating the layout a challenge. Although perhaps I could use the C-preprocessor to build complete pages from the layout + sub-pages. I might explore this if there is no "obvious" answer to my query.)


Replies are listed 'Best First'.
Re: Nested HTML::Template usage (TT2/Xslate/sub)
by Anonymous Monk on Aug 29, 2014 at 02:03 UTC

    some food for thought on other options ( TT2/Xslate/sub )

      I suspect that migrating to Template::Toolkit would be significant amount of work, given how many templates/pages I'd have to handle, and also upating the loop-structures which currently get passed to HTML::Template.

      Text::Xslate looks interesting, thanks for the link. If the compatibility is 100%, or near to it, then it might make sense to examine it.

      For the moment I've written a simple perl script, (what else?), to take each of my page-snippets and the global layout file and just build a complete "layout+content" file for each one. That solves my immediate problem, and means I keep the benefit of one easy-to-update layout template.

      Although I'm largely the person responsible for the site others do contribute at times, and it would be nice to avoid adding extra hurdles to that process.

Re: Nested HTML::Template usage
by MidLifeXis (Monsignor) on Aug 28, 2014 at 13:18 UTC

    How about the filter option?

    Update: Hmm, not certain how I missed that in your original post. Move along. Nothing to see here.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1098839]
Approved by AppleFritter
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2021-02-28 20:44 GMT
Find Nodes?
    Voting Booth?

    No recent polls found