yahermann
yahermann

Reputation: 1569

More than one layout/wrapper with Dancer and Template::Toolkit

I followed this recipe to disable Dancer's "layout" and re-enable TT's "WRAPPER":

How to make a page-specific title in Dancer templates?

which appears to be necessary to change tokens within the layout/wrapper at the route level. Briefly, the linked recipe requires specifying a single layout/wrapper in the config.yml file.

The recipe works great when using one layout/wrapper, but how do I go about changing (or disabling) the template layout/wrapper at the route level?

Since Dancer's native layout is disabled, this does not work:

 template('mytemplate', { ... }, { layout => 'some_other_layout' });   # NO GOOD

Also, I tried changing the config prior to rendering template, but that doesn't appear to work either:

 # ALSO NO GOOD
 config->{'engines'}->{'template_toolkit'}->{'WRAPPER'} = 'some_other_layout';
 return template('mytemplate', { ... });

And I also tried using the Dancer set/setting, but also no good:

 # ALSO NO GOOD
 my $engines = setting('engines');
 $engines->{'template_toolkit'}->{'WRAPPER'} = 'some_other_layout';
 set engines => $engines;

Any ideas?

Upvotes: 1

Views: 1356

Answers (3)

yahermann
yahermann

Reputation: 1569

I think I figured it out. Thanks to Yanick and to the link referenced in my other answer (Kludgy Workaround #2) for the inspiration. Here's the recipe:

  1. Create a single wrapper file for use in your entire project, and make it:

    <% IF layout %>
    <% INCLUDE "$layout" %>
    <% ELSE %>
    <% content %>
    <% END %>
    
  2. Within your route:

    return template('mytemplate', {
      layout => 'layouts/some_layout.tt',
      param1 => data1,
      param2 => data2,
      ...
      });
    

And bingo, you're done. Leave out the layout parameter, and will get no layout at all.

Upvotes: 3

yahermann
yahermann

Reputation: 1569

Two incredibly kludgy workarounds (please don't hate me):

Kludgy Workaround #1

set template => 'simple';
my $html = template('mytemplate', {}, { layout => 'some_other_layout' });
set template => 'template_toolkit';
return $html;

Basically, we temporarily switch out template_toolkit for Dancer's 'simple' template renderer.

Kludgy Workaround #2

Give up and keep the WRAPPER, but add conditionals so that it gets itself out of the way as described in this post:

How can I override WRAPPER in a Template Toolkit template file?

Upvotes: 0

Yanick
Yanick

Reputation: 1280

I'm no TT expert, but it seems that once WRAPPER is set for the TemplateToolkit object, it can't be changed.

If that's the case, here's a slightly devious workaround.

  1. Set the layout to be, say, 'base.tt'.

  2. make that layout to be:

    print $context->process( $stash->get('wrapper'), { content => $context->process( $stash->get( 'template.name' ) ) });
  3. and then in your route:

    get '/' => sub { template 'index', { wrapper => 'layouts/main.tt' }; };

Tadah!

This being said, if you are using Dancer's native layouts, the tokens you're passing to template should make it to the wrapper code.

Upvotes: 1

Related Questions