I am developing a Catalyst app which uses Template::Toolkit
as template engine. One page needs a list of equal input elements. They can be taken from an array but I need both sort order and a descriptive label for the element.
For having a sort order I would use an array. For storing an additional value per key a hash is perfect. How to combine both in TT? I could use both things but that seems ugly and can cause mistakes when changing the fields.
However, I prefer doing this in TT because both the descriptions and the order of form elements is a front-end thing.
This is how I would do it in pure Perl:
#!/usr/bin/perl -w
use 5.10.0;
# definition of description and order in 1 step
my @fields = (
property_foo => "Some property",
property_bar => "Important field",
property_baz => "Something else",
);
# extract information
my %descriptions = @fields;
my @order = @fields[grep {($_ + 1) % 2} 0..(scalar @fields - 1)];
say "=== natural perl sort order ===";
foreach (keys %descriptions) {say $_};
say "=== wanted output ===";
foreach (@order) {
say $descriptions{$_} . ": [label for $_]";
}
Outputs:
=== natural perl sort order ===
property_baz
property_foo
property_bar
=== wanted output ===
Some property: [label for property_foo]
Important field: [label for property_bar]
Something else: [label for property_baz]
This is what I write in my template:
[%
order = (
property_foo,
property_bar,
property_baz,
);
descriptions = {
property_foo => "Some property",
property_bar => "Important field",
property_baz => "Something else",
}
FOREACH property IN order %]
[% descriptions.$property %]: <input name="[% property %]" />
[% END %]
However, it is really ugly to have the same information (list of fields) twice. I want to avoid editing the list twice and with a longer list of fields it gets really annoying (about 20 items, not long enough to do some database stuff).
If you need ordering and multiple pieces of information then you should consider an array of hash references.
my @fields = (
{ id => 'property_foo',
label => 'Some property' },
{ id => 'property_bar',
label => 'Important field' },
{ id => 'property_baz',
label => 'Something else' },
);
foreach (@fields) {
print "ID: $_->{id}, Label: $_->{label}\n";
}
If the complexity increases much beyond this, you might consider replacing the hashrefs with real objects.
And, in TT, it looks like this:
[%-
properties = [
{id => 'property_foo',
label => 'Some property'},
{id => 'property_bar',
label => 'Important field'},
{id => 'property_baz',
label => 'Something else'},
];
-%]
[%- FOREACH property IN properties %]
[% property.label %]: <input name="[% property.id %]" />
[% END %]