use CGI::Application::Plugin::TmplInnerOuter;


GOAL 1: INNER OUTER CONCEPT Have 1 main template, into which the other templates for each runmode are inserted I dont want to have to stick TMPL_INCLUDE for a header and footer So for runmode 'daisy', i want to use daisy.html but also main.html into which daisy.html goes.

GOAL 2: HARD CODED TEMPLATES WITH OPTION TO OVERRIDE I want to define a template hard coded, and offer the option to override by the user- by simply making the template exist where we suspect to find it. This is done with HTML::Template::Default

GOAL 3: Provide a means via which we store all parameters that will go into the template later, and at the last state output to browser.


The outer template should hold the things that are present in every page, in every runmode view. Your header, logout buttons, navigation, footer etc.

First you can to define your main template.


   <title><TMPL_VAR TITLE></title>

This can either be saved as 'main.html' or it can be Set Hard Coded. If you set it hard coded into your app, if the main.html file exists, it overrides the hard coded version. This is how you can include your template code in your modules but still let people override them.

How you would Set Hard Coded, main.html:

   <title><TMPL_VAR TITLE></title>

The very basic template shown above for main is already included. You can override it as shown above. This means you can safely code whatever inside guts, and change the look and feel of the app radically by creating a main.html file on disk, and doing what you want with it!


Then you have to set an inner template, this is the template relevant to your current runmode. If your runmode is 'continue' then template sought is 'continue.html' When setting a default inner template, the name argument does not need be provided.

   sub continue : Runmode {
      my $self = shift;
      $self->_set_tmpl_default( q{<h1>Would you like to continue?</h1>} );

      return $self->tmpl_output;

Another example; your runmode being 'jimmy'.. this is what you would do:

   sub Jimmy : Runmode {
      my $self = shift;
      my $default = q{<p> I said: <TMPL_VAR BLABLA> </p>};

      $self->_set_vars(   BLABLA => 'This is what I said.' );
      # or
      $self->tmpl->param( BLABLA => 'This is what I said.' );

      return $self->tmpl_output;

If you have Jimmy.html file in TMPL_PATH, then it is used as the inner template, regardless if you hard code it.


All methods are exported.

tmpl_inner_name() and tmpl_inner_name_set()

name of inner template name, by default we use the current runmode, if you pass string 'this' to set, will look for this.html for the inner template


argument is your html template code. this is what would go in HTML::Template::Default::get_tmpl();

optional argument is a name of the template, such as 'main.html'. If you do not specifiy a page name, it is assumed you are setting the inner template's default code. The runmode appended by .html is the page name.

To set outer (main) template:

   $self->_set_tmpl_default( $maincode, 'main.html' );

tmpl(), _inner_tmpl(), _tmpl()

returns inner template HTML::Template object. You can use this, but I suggest you instead set variables via _set_vars() tmpl_output() will later insert them, and insert the inner template output into the main template.

_tmpl_inner() also returns inner template, so would _tmpl() with no arguments.

tmpl_main(), _outer_tmpl(), _tmpl('main.html')

returns outer template HTML::Template object. So would _tmpl_outer() and _tmpl('main.html')


if your runmode is goop, this returns goop.html


these are exported, you do not have to use them

_set_vars(), tmpl_set()

Argument is hash. Sets variables that later will be inserted into templates tmpl_set() is an alias for _set_vars()

Returns hashref of what the vars set are presently. If you call before setting else, will return undef.

Instead of use tmpl->param( KEY => VAL ) ... use...

      USER  => 'Joe',
      TODAY => time_format('yyyy/mm/dd', time)

And then

   $self->_feed_vars( $tmpl);

It is NOT presently supported to pass undefined values, if you do, they are silently ignored.

   $self->_feed_vars( PARAM => undef );


argument is HTML::Template object feeds vars into template



print to STDERR all vars that will be fed, sorted optional arg is boolean to print in an orderly fashion



combines the inner and outer templates, feeds variables, returns output. this should be the last thing called by every runmode You may want to override the default output method, to insert other things into it.

Example 1:

   sub show_cactus : Runmode {
      my $self = shift;      
      my $html = q{
       <h1><TMPL_VAR TITLE></h1>
       <p>your html template code.</p>
       <small><TMLP_VAR MESSAGE></small>

         TITLE => 'This is the title, sure.'
         MESSAGE => 'Ok, this is text.',


      # every runmode that shows output should use this:
      return $self->tmpl_output;

Example 2:

The next example does the same exact thing, imagining you have a show_cactus.html template on disk, in TMPL_PATH (see CGI::Application).

   sub show_cactus : Runmode {
      my $self = shift;      
         TITLE => 'This is the title, sure.'
         MESSAGE => 'Ok, this is text.',
      return $self->tmpl_output;      

The arguments to _set_vars are fed to both the inner template (show_cactus.html) and the outer template (main.html). All of the code of the inner template will be inserted into the <TMPL_VAR BODY> tag of the outer template. So, your inner template should not have html start and end tags, body tags etc.

Overriding default tmpl_output()

The default out simply feeds output to the inner and outer templates. At any point in the application from any method you can call _set_vars() to preset variables that will be sent to both inner and outer templates (harmless with this system). Maybe you have a navigation loop for example that you want to insert just at the last moment.

If so.. here is one example:

   no warnings 'redefine';
   sub tmpl_output {
             my $self = shift;
           $self->_set_vars( NAVIGATION_LOOP => $self->my_navigation_loop_method );
           $self->_debug_vars();  # prints to STDERR all the vars
           $self->_debug_vars(1); # prints to STDERR all the vars, in an orderly fashion

           return $self->_tmpl_outer->output;
      # or return $self->tmpl_main->output;
      # or return $self->_tmpl('main.html')->output;     

This way all runmodes returning tmpl_output() don't need to change anything about them.


takes no argument feeds any vars set with _set_vars() into both inner and outer templates returns true.


inserts output of inner template into outer template. (inserts output of runmode template into main template.) returns true.


For a great example of this module in action please see CGI::Application::Gallery.


Leo Charre leocharre at cpan dot org


HTML::Template HTML::Template::Default CGI::Application LEOCHARRE::DEBUG