Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl Dancer Template headers, footers

I'm learning Perl and using Dancer as a web framework. I've got two views (tt files) which should share the same navigation. So, it would be great to start learning how to manage templates for navigation and footers.

I've read the documentation for the Template Toolkit and I've done the following:

I've changed the config.yml file to:

#template: "simple"

template: "template_toolkit"
engines:
     template_toolkit:
     start_tag: '[%'
     end_tag:   '%]'

I've defined the templates in the .pm file:

package proyecto;
use Dancer ':syntax';

our $VERSION = '0.1';

get '/' => sub {
    template 'index';
};


get '/menu' => sub {
    template 'menu';
};

true;

There is a link in the index template directing the visitor to the menu template:

<li class="active">< a href="/menu">Menu <span class="sr-only"></span></a></li>

I would like to reuse the navigation code from index.tt into menu.tt, so I've wrapped the navigation code in index.tt with the following:

[% BLOCK navigation %]
#my nav code
[% END %]

To finally include that code in the menu.tt file, I've written the following (where the navigation code should be):

[% navigation = 'index.tt' %]
[% INCLUDE navigation %] 

The files index.tt and menu.tt are located in the folder views. But it seems it's not that easy! =( Any suggestion on how to reuse code from one file to another which is located in the same directory?

like image 239
Chüngel Avatar asked May 03 '16 15:05

Chüngel


2 Answers

This is what layouts are for. The idea is that content common to all pages (e.g. header, footer, navbar) goes in the layout and content specific to each page goes in templates called views. Views are called "partials" in other frameworks because they only contain the content for part of the page.

If you use the dancer command line utility to set up your application, the default layout is views/layouts/main.tt and looks something like this:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=<% settings.charset %>" />
  <title>Foo</title>
  <link rel="stylesheet" href="<% request.uri_base %>/css/style.css" />
</head>
<body>
  <% content %>
  <div id="footer">
    Powered by <a href="http://perldancer.org/">Dancer</a> <% dancer_version %>
  </div>
</body>
</html>

The <% content %> section is replaced with the specified view when you call template 'view';. (In your case, you'll need to change <% and %> to [% and %] since you're using the Template Toolkit-style delimiters.)

For example, if views/index.tt is:

<h1>Hello, World!</h1>

calling template 'index'; in a route renders the following:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
  <title>Foo</title>
  <link rel="stylesheet" href="http://www.example.com/css/style.css" />
</head>
<body>
  <h1>Hello, World!</h1>
  <div id="footer">
    Powered by <a href="http://perldancer.org/">Dancer</a> 1.3202
  </div>
</body>
</html>

Note that there's already a footer section; you just have to add elements for a header and navbar.

If this is new development, you should really be using Dancer2 instead of Dancer (fortunately, layouts and views are the same in both).

like image 52
ThisSuitIsBlackNot Avatar answered Oct 20 '22 01:10

ThisSuitIsBlackNot


The [% INCLUDE %] directive's argument can be interpreted in one of two ways.

  1. The name of another template file
  2. The name of a block that is defined in the current template file (or in another template file which has included the current template file).

All of which means that your current plan won't work. menu.tt won't see any block defined inside index.tt.

There are a couple of better solutions though.

Firstly, consider moving the navigation code into a third, separate, template file. You can then INCLUDE this template into both index.tt and menu.tt.

Secondly, you can use Dancer's "layout" feature. This is a template that is wrapped around your view templates. Typically the layout template contains the navigation and all standard page furniture (like headers and footers). It also contains a [% content %] directive. When a view is rendered, the rendered version is dropped into the layout template in the location of the [% content %] directive. See the Layouts section in Dancer::Tutorial for more information.

p.s. I see you're using Dancer. I'd highly recommend switching to Dancer2.

like image 36
Dave Cross Avatar answered Oct 20 '22 00:10

Dave Cross