[Templates] FOREACH enhancement request

robbin.bonthond@philips.com robbin.bonthond@philips.com
Thu, 2 Oct 2003 14:47:45 +0200


Hello,

I am using TT2 v2.10, and I am having problems with my loops.

Lets say I have a list of books that I want to print. This is the template:

[% FOREACH book=books.book %]
[% book.title %]
[% END %]

And this is the code to process the templates:

my $tt = new Template();
my $config={
    books => {
        book => [
            { title => "title1" },
            { title => "title2" },
        ]
    }
};
$tt->process("test.tt2",$config,"test.out") or print $tt->error()."\n";

However, If my $config only has one book defined, it would look like this:
(in real life I am importing a XML file with XML::Mini)

my $config={
    books => {
        book => { title => "title" },
    }
};

and that does not work with my templates, because the FOREACH loop will only process arrays.

So I created my own plugin to convert a hash to a array-of-hashes:

package MyTemplate::Plugin::HashToHashedList;
use base qw(Template::Plugin);
use strict;
sub load {
    my ($class, $contect)=@_;
    $Template::Stash::SCALAR_OPS->{array} = sub { @_ };
    $Template::Stash::LIST_OPS->{array} = sub { @_ };
    $Template::Stash::HASH_OPS->{array} = sub { [ @_ ] };
    return $class;
}
1;

and modified my templates :

[%- USE HashToHashedList %]
[% FOREACH book=books.book.array %]
[% book.title %]
[% END %]

and they work again, for single hash values, and lists.

Since FOREACH constructs are always used on arrays,
could TT2 be modified to always convert things to arrays in loops ?

With regards,

Robbin