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

I am using HTML::Template in a webapp where I have a single template with a set of style sheets that gives the entire site its look and feel. I have form generation and validation code based on CGI::FormBuilder for some 200 forms with corresponding templates for each form.

What I would like to do is be able to have the <TMPL_INCLUDE 'filename.tmpl'> be controllable so that I can specify which template is to be included in the content <div> before the template is passed to CGI::FormBuilder.

Thinking about the problem I could:

  1. Use another templating system to put the include name into the page template.
  2. Leave the INCLUDE name the same, but rename the form template before the template is passed (or maybe copy it and then it is over-written when the next template is built)

But neither of these methods is safe in the mod_perl context. So I could:

I feel I am getting a little over my head here. If need be I can create a special module to handle this, but I am not sure how it would be best to go about it.

jdtoronto

Replies are listed 'Best First'.
Re: HTML::Template question.
by hardburn (Abbot) on Nov 17, 2003 at 19:07 UTC

    The way I've solved similar problems is to load two seperate HTML::Template objects. Instead of the <TMPL_INCLUDE>, it's instead a <TMPL_VAR> that is filled in with the data from another HTML::Template object. Not particularly elegant, but it works.

    It'd be nice if HTML::Template had something like a switch statement so these things could be dispatched easier, though I suspect the developers would be very hesitant to add one. Code-and-data-are-seperate, and all that.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      You've hit the nail on the head.

      I could pass the FORM TEMPALTE through CGI::FormBuilder, parse it to recover the JS for the HEAD and put that into one <TMPL_VAR ...> and the put the HTML for the BODY into another <TMPL_VAR ...>. Sounds like a not so difficult piece of code.

      I just got an email back from Nathan Wigger (author of CGI::FormBuilder) to say that in v3.0 you will be able to pass a HTML::TEmplate object into FormBuilder, this would make it trivial.

      See, amazing what a fresh brain and another mug of coffee can do to a problem :)

      jdtoronto

Re: HTML::Template question.
by jeffa (Bishop) on Nov 17, 2003 at 19:15 UTC
    I too, have used two template objects to solve this problem:
    use strict; use warnings; use HTML::Template; use Inline::Files; my $skeleton = HTML::Template->new(filehandle => \*SKELETON); my @page = ( HTML::Template->new(filehandle => \*PAGE1), HTML::Template->new(filehandle => \*PAGE2), ); for (@page) { $skeleton->param(body => $_->output); print $skeleton->output; } __SKELETON__ <html> <body> <tmpl_var body> </body> </html> __PAGE1__ hello world __PAGE2__ foo bar baz qux
    But, these days i prefer to use Template with it's ultra handy WRAPPER construct. I am sure that Template essentially has to do the same thing: load a seperate template and substitute values, but it does it for me. :) For example, all i need to do is create the skeleton (i'll call it skeleton.html)
    <html> <head> <title>[% title %]</title> </head> <body> [% content %] </body> </html>
    And some pages:
    (page1.html) [% WRAPPER skeleton.html title="Page 1" %] hello world [% END %] ----------------------------------------------- (page2.html) [% WRAPPER skeleton.html title="Page 2" %] foo bar baz [% END %]
    And i'm done. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: HTML::Template question.
by eric256 (Parson) on Nov 17, 2003 at 19:10 UTC

    It sounds like you want to do dynamic includes (where the include file is different each run) in HTML::Template. The last time i wanted to do something like this, instead of includeing the file in the template, i put a scalar there, and then filled the scalar in with the output of the template in the perl code. Hmm that came out kinda garbeled. Instead of haveing HTML::Template do the include for you, you can figure out wich template you want included and get its output (inside your perl code), then store that output in a variable that is in the original template. Its a messy hack, but i believe its the only way to do this kinda thing in HTML::Template.

    update: hardburn said it alot clearer than me ++


    ___________
    Eric Hodges