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

Hello Monks. There seems to be a topic in HTML::Template that I simply cannot wrap my feeble little mind around: complext data structures within loops.

Here's what I'm trying to output, as an example:

Where the list of states is not always the same, and the number of people listed for each state is not always the same.

my first inclination was to have something like this

@array = [ state => "Alaska"<BR> names => "Name One, Name Two" ]

except theres no way to split the names up in a template doc ... so I'm a lil confused. Anyone point me in the right direction? Thanks!

- Erik

Replies are listed 'Best First'.
Re: HTML::Template Loop Question
by blokhead (Monsignor) on Sep 23, 2003 at 21:11 UTC
    I often find it helpful to think about the template first and then see what the data structure that fills it would have to look like. This is how I'd write a template for the output you want:
    <ul> <TMPL_LOOP states> <li> <TMPL_VAR state> <ul> <TMPL_LOOP people> <li> <TMPL_VAR person> </TMPL_LOOP> </ul> </TMPL_LOOP> </ul>
    Now that we know where the loops and vars go, we can figure out what kind of data structure we need. TMPL_LOOPs need something like loop_name => [ { .. }, { .. }, .. ]. (A reference to an array of hash references). TMPL_VARs just need var_name => "scalar". So in order to fill out this template, you'll need data that is structured like this:
    my @states = ( { state => "Alaska", people => [ { person => "Joe Blow" }, { person => "Peter TorkM" } ] }, { state => "California", people => [ { person => "Lily White }, { person => "Erik Svendater" } ] }, ... ); $tmpl->param( states => \@states );
    If you have your data already in some other form, and have questions about how to get it into a data structure like this, let us know and we can probably help with that too..

    blokhead

      And just in case the data was originally stored in a hash like so:
      my %state = ( Alaska => ["Joe Blow", "Peter Tork"], California => ["Lily White","Erik Svendater"], Florida => ["Fred Flinstone", "Barney Rubble", "Judy Jetson"], );
      Here is some code to munge that data into what HTML::Template needs:
      my @state = [ map { state => $_, people => [ map {person => $_}, @{$state{$_}} ], }, sort keys %state ];

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      

      Thank you *SO* much. I made a test file with just your datastruct and the HTML you had above ... ran exactly as it should of.

      So its ... an array of hashes and arrays of hashes (I think). To be completely honest, I still don't understand precisely why it is working, but it is working ... I'll spend some time pondering it out later so that I can repeat it in different contexts.

      Again, Thanks!

      For sure ++

      - Erik

      <ul> <TMPL_LOOP people> <li> <TMPL_VAR person> </TMPL_LOOP> </ul>
      <nit>

      Not having used these templates myself yet, I may be spouting off without cause here, but shouldn't you close off the li?

      <ul> <TMPL_LOOP people> <li> <TMPL_VAR person> </li> </TMPL_LOOP> </ul>
      </nit>

      $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
        www.w3.org says it's optional:
        The end tag for LI elements can always be omitted.

        blokhead

      I wanted to write another reply and say thanks again. Once I *really* studied the concrete example it started to make sense. Well, eventually.

      I was able to build a much more complicated HTML::Template datastructure this morning without too much difficulty (okay, a little, but hey, this has dogged me for 3 months now).

      I just love perlmonks.

      - Erik

Re: HTML::Template Loop Question
by Enlil (Parson) on Sep 23, 2003 at 21:20 UTC
    There is a section in the documentation that mentions "<TMPL_LOOP>s within <TMPL_LOOP>s are fine and work as you would expect."

    This is untested but should get you going in the right direction:

    in your script

    and then in your TEMPLATE: This will probably need some tweaking.. but should give you an idea of how to proceed.

    -enlil