Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Variable include names in HTML::Template

by dsheroh (Monsignor)
on Feb 29, 2008 at 18:47 UTC ( [id://671259]=perlquestion: print w/replies, xml ) Need Help??

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

Brothers,

I am in the habit of using HTML::Template to generate formulaic output text (HTML or otherwise), but I now find I am accumulating large numbers of templates which are all of the form

<html> <head> # various information </head><body> <tmpl_include header.tpl> <tmpl_include sidebar.tpl> <div id=content> # actual content </div> <tmpl_include footer.tpl> </body> </html>
This causes much duplication, which bit me today as I needed to make a layout change on a site with about 20 such templates and this change required the addition of a second 'wrapper' div surrounding the existing 'content' div. It was not an incredibly time-consuming task, but definitely tedious.

This got me thinking that it would be better if I could have a single template establishing that full structure and then <tmpl_include <tmpl_var pagename>.tpl> the actual content based on which page was being loaded at the time. Unfortunately, my various attempts to identify a syntax which allowed this proved futile.

Is there an established way to accomplish this other than by having the content template include two independent templates for the leading and the trailing portions? (I prefer to keep open tag/close tag pairs within the same file so it's easier to verify that they're matched. It's also the only way to have any hope of doing useful validation of the templates themselves.)

While composing this message, it occurred to me that I could read in the meta-template file and use a regex to insert the name of the proper page content template before passing it to HTML::Template for final processing, but I would like to think that there's a better, cleaner way to do it.

Replies are listed 'Best First'.
Re: Variable include names in HTML::Template
by friedo (Prior) on Feb 29, 2008 at 20:34 UTC

    Template Toolkit has a WRAPPER directive which works marvelously, but it doesn't seem that HTML::Template has an equivalent.

    As a solution, perhaps you could render the content template, then pass that result to a second template which has the header/footer stuff and a <tmpl_var> for the content.

Re: Variable include names in HTML::Template
by Tanktalus (Canon) on Feb 29, 2008 at 23:28 UTC

    All I did was to create my own FillTemplate subroutine that took as parameters:

    header => 0|1
    defaults to true
    footer => 0|1
    defaults to true
    tmpl => $filename
    required parameter
    params => {...}
    any parameters that need passing to HTML::Template
    and others. In my case, header would include the <html><head> and <div id="content> from your example, so that the actual template would only be the actual content. I even had flags for post-processing (e.g., I had a post-processing function that would parse the whole output as XML, and then go in and mark up tables such that headers would be repeated every x rows, and alternating data rows would get alternating backgrounds to make it a bit easier to read). And then all this would be concatenated and returned from the function, just like HTML::Template does.

    Depending on your needs, you could have multiple headers as parameters, each with an appropriate default. Whenever I found myself doing something over and over again, it got folded into a parameter to FillTemplate. Admittedly, Template-Toolkit changes all this - I can use blocks to do the same things, with more flexibility, and more explicitly, though it also makes my templates more verbose.

Re: Variable include names in HTML::Template
by wfsp (Abbot) on Mar 01, 2008 at 08:34 UTC
    Perhaps turn the problem inside out.

    If the header, sidebar and footer is static across your templates you could put all that html in a "master" template and have the variable content as a TMPL_VAR. You would then run HTML::Template twice. Once to create the content, populating any params as appropriate, and then supply that to the "master". The heavy lifting is done by your code and you leave HTML::Template to worry about what it looks like.

    Any site wide changes, such as adding an additional wrapper around the content (and you can never have too many wrappers imo) would then only need to be added to the "master". You can have a complete site redesign by changing one template and there would then be no need to trouble any of the individual "content" templates. I've learnt at great cost that is a very good thing indeed.

    Slightly more work perhaps but I think the flexibility/maintainability it buys you is well worth it.

      Thanks for the suggestion! That's exactly what I wanted to accomplish (whether I explained it clearly or not), but having HTML::Template itself handle both passes hadn't occurred to me.

      I doubt that it would take more than one or two site-wide changes to more than make up for the extra work involved in setting it up. (Plus one extra site-wide change in my case, since I'll need to make a site-wide change in the process of doing so...) And how many sites go their entire lifetime with only one or two site-wide changes?

Re: Variable include names in HTML::Template
by reneeb (Chaplain) on Mar 01, 2008 at 12:26 UTC
    Have a look at HTML::Template::Compiled.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://671259]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (2)
As of 2024-04-25 21:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found