Template Toolkit is an excellent and very powerful templating language. In this example we'll see how can we display a hash of hashes.

Plain Text display

In the script you can see the data structure that was taken, with slight modifications from a question that was posted to the Perl Dancer mailing list.

examples/tt_hoh/create.pl

use strict;
use warnings;
use Template;

my %payload = (
    'TylerMontgomery(2022)' => {
                             'so' => 1,
                             'bb' => 1,
                             'rbis' => 0,
                             'atbats' => 117,
                             'runs' => 2,
                             'hits' => 2
                           },
    'ChaseLangan(2022)' => {
                               'runs' => 4,
                               'hits' => 24,
                               'atbats' => 5,
                               'bb' => 0,
                               'rbis' => 2,
                               'so' => 1
                             },
    'BryceJones(2021)' => {
                      'hits' => 2,
                      'runs' => 2,
                      'atbats' => 4,
                      'bb' => 2,
                      'rbis' => 4,
                      'so' => 1
                    },
);


my $tt = Template->new({
    INCLUDE_PATH => './templates',
    INTERPOLATE  => 1,
}) or die "$Template::ERROR\n";

my %data = (
    payload     => \%payload,
);

my $report;
$tt->process('report.tt', \%data, \$report) or die $tt->error(), "\n";
print $report;

First let's see a template to display the data in plain text format. This template actually includes two examples. In the first one we just iterate over the keys of the external hash and then the keys of each on of the internal hashes.

In the second example we have a rather well-formatted table.

examples/tt_hoh/templates/report.tt

[% FOR name IN payload.keys.sort %]
    [% name %]
    -------------
       [%- FOR field IN payload.$name.keys.sort %]
           [% field %] : [% payload.$name.$field -%]
       [% END %]
[% END %]

===============================================

[% USE String %]

Name                    atbats so   bb  rbis hits runs
[% FOR name IN payload.keys.sort %]
[% fname  = String.new(name) -%]
[% atbats = String.new(payload.$name.atbats) -%]
[% so     = String.new(payload.$name.so) -%]
[% bb     = String.new(payload.$name.bb ) -%]
[% rbis   = String.new(payload.$name.rbis) -%]
[% hits   = String.new(payload.$name.hits) -%]
[% runs   = String.new(payload.$name.runs) -%]
[% fname.left(22)  %] [% atbats.right(3) -%]    [% so.right(3) -%] [% bb.right(3) -%]  [% rbis.right(3) -%]   [% hits.right(3) -%]  [% runs.right(3) -%]
[% END  %]


    BryceJones(2021)
    -------------
           atbats : 4
           bb : 1
           hits : 2
           rbis : 4
           runs : 2
           so : 1

    ChaseLangan(2022)
    -------------
           atbats : 5
           bb : 0
           hits : 24
           rbis : 2
           runs : 4
           so : 1

    TylerMontgomery(2022)
    -------------
           atbats : 117
           bb : 1
           hits : 2
           rbis : 0
           runs : 2
           so : 1


===============================================



Name                    atbats so   bb  rbis hits runs

BryceJones(2021)         4      1   1    4     2    2
ChaseLangan(2022)        5      1   0    2    24    4
TylerMontgomery(2022)  117      1   1    0     2    2

HTML page

Creating an HTML page using this template is a lot easier as we don't have to worry about padding with spaces. That's handled by HTML and CSS.