1

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?

Community
  • 1
  • 1
yahermann
  • 1,539
  • 1
  • 12
  • 33

3 Answers3

3

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.

yahermann
  • 1,539
  • 1
  • 12
  • 33
1

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.

Yanick
  • 1,250
  • 8
  • 9
  • Hi Yanick, 1st & foremost, thanks for your devious :) answer. I'm unclear how to do step #2; am I to include the perl code you suggested in an html'ish layout somehow? Also I'm assuming that in step #1 I'm setting WRAPPER to 'base.tt'? – yahermann Aug 31 '13 at 22:03
  • The code in step #2 is meant to be the content of base.tt, and to be surrounde dby [%PERL%] ... [%END%]. But it's the same thing, in spirit, than the accepted solution you wrote below. Your solution is a little nicer too, as it stays in pure TT space, and doesn't resort to perl code. Well done. :-) – Yanick Sep 01 '13 at 20:47
0

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?

Community
  • 1
  • 1
yahermann
  • 1,539
  • 1
  • 12
  • 33