Template wrappers

Template Toolkit has an option to wrap every page in another template. This provides and easy means of applying a common structure to your site. For example, you can place a header and footer or your navigation into the wrapper and it will be rendered on every page.

Here's an example of a simple wrapper:

<!doctype html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>[% page.title || "Your default title goes here" %]</title>
        <link rel="stylesheet" href="/style.css" media="all">
    </head>
    <body>
<h1>[% page.title %]</h1>
[% content %]
    </body>
</html>

It applies a basic HTML document structure, a title, and a CSS stylesheet, but obviously you can expand this to contain a header, footer, your site's navigation or any other common elements.

With this saved as wrapper.tt2 in your template root directory, it can be applied to all your pages by adding the following to your TT view configuration:

WRAPPER => 'wrapper.tt2'

You may have noticed the [% page.title %] call in the template above. Due to the way wrappers are processed, they have access to variables set in the templates they are wrapping. This means you can pass data to the wrapper simply by setting variables it knows about. In this case you can set a title for your page from within your content templates by doing:

[% page.title = 'Welcome Page' %]

If one isn't provided, then it'll use whatever default you provide in your template.

Custom wrappers for parts of your site

You may find that having the same wrapper for every page is not sufficient. You may want, for example, a different wrapper for a login page, or no wrapper at all if you're outputting HTML for use with AJAX calls.

To do this you can create a more intelligent wrapper function that can change its behaviour based on values you set in the stash. Here's an example of a cleverer wrapper.tt2:

[% IF no_wrapper;
        debug("Passing page through as text: $template.name");
        content;
    ELSE;
        wrapper = wrapper || 'site/layouts/full.tt2';
        debug("Applying wrapper $wrapper to $template.name");
        content WRAPPER $wrapper;
    END;
-%]

This supports two new stash variables that you can set in your controllers: wrapper which can contain the name of the wrapper you wish to use (in this example I've moved the original wrapper defined above to site/layouts/full.tt2), and no_wrapper to disable the wrapper completely. If you don't supply a wrapper to use (or set no_wrapper) then the default site/layouts/full.tt2 will be used.

To use this, you can simply add the relevant stash variable in your controller, for example:

sub login :Local {
    my ( $self, $c ) = @_;

    # We don't want the site navigation on the login page, so we'll set a 
    # special wrapper here that doesn't include it.
    $c->stash->{wrapper} = 'site/layouts/minimal.tt2';

    $c->stash->{template} = 'login.tt2';
}

If you want every action in a controller class to use a specific wrapper then you can set it in the begin action:

sub begin :Private {
    my ( $self, $c ) = @_;

    # Apply a fancy layout to every action in this controllers
    $c->stash->{wrapper} = 'site/layouts/fancy.tt2';
}

See Also

My tags:
 
Popular tags:
 
Powered by Catalyst
Powered by MojoMojo Hosted by Shadowcat - Managed by Nordaaker