dariusj has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I am trying to sort a hash of hashes of the form { 1 => { customer_class_id => 1, discount => "0.000", name => "None" }, 2 => etc. } by name alphabetically in template toolkit.

I currently have this:

[% FOREACH category_id IN category.keys.sort($category_id.name) %] [% IF category.$category_id.customer_class_id == class_id %] <option value="[% category_id %]">[% category.$category_id.nam +e %]</option> [% END %] [% END %]

Everything's displaying fine but it's not sorting correctly!

Any tips please?

Replies are listed 'Best First'.
Re: Sort a hash of hashes by value in template toolkit
by Somni (Friar) on Nov 16, 2007 at 15:15 UTC
    The sort (and nsort) methods are necessarily limited. You might be looking for the pairs method. See Template::Manual::VMethods.

    If your sorting needs are at all complex you're going to have to pass it to some Perl to handle. Either a variable that's a subroutine, or a template plugin.

      Gave up on doing it in template toolkit, solved the issue by having a perl method in the handler that returns a sorted array of arrays which can then be easily looped in the .tt file.

      An ugly solution, but it works.

        I came across this issue as well. I was passing a hash of hashes to TT and used this method to sort it.
        Sample Hash:
        %Orders = {}; $Orders{1}{NAME} = 'Bill'; $Orders{1}{STATUS} = 'Complete'; $Orders{2}{NAME} = 'John'; $Orders{3}{STATUS} = 'Pending';

        Sort the hash by key value (orderid) descending and output data from the nested hashes:

        <table> <tr> <th>Order ID</th> <th>Name</th> <th>Status</th> </tr> [% sortedKEYS = Orders.nsort %] [% FOREACH skey IN sortedKEYS %] <tr> <td>[% skey %]</td> <td>[% Orders.$skey.NAME %]</td> <td>[% Orders.$skey.STATUS %]</td> </tr> [% END %] </table>
Re: Sort a hash of hashes by value in template toolkit
by jbert (Priest) on Nov 16, 2007 at 12:34 UTC
    This is why I don't like additional "little languages" like template toolkit. We have a good language with if's and loops in it to hand - perl. (I'm a fan of the Text::Template approach.).

    There's probably a way of doing what you want in TT, but I'd personally avoid doing that and do the sort in perl. So you could populate an array with the data sorted in the order you need, then use a simpler piece of TT to do the output.

    In general, I'd advise keeping the TT as simple as possible and doing as much as possible in perl.