Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

HTML::Template - Two columns?

by mikeB (Friar)
on Jul 03, 2001 at 23:15 UTC ( #93641=perlquestion: print w/replies, xml ) Need Help??

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

I currently have a CGI page, using HTML::Template, which builds a table using <TMPL_LOOP>. The table can get long, so I'd like to make two parallel sets of columns.

The first thought was to pass two arrays, one for the left column and one for the right. It doesn't appear that there is a way to index through two arrays at once, though.

Twice the number of hash entries in a single array looks like it could work, but seems messy.

Is there a better way to do this?

Replies are listed 'Best First'.
(dkubb) Re: (2) HTML::Template - Two columns?
by dkubb (Deacon) on Jul 04, 2001 at 06:05 UTC

    What you want to do is possible, but requires you to use an underused feature in HTML::Template called loop_context_vars. Enabling it in the new() constructor will allow you to use the loop context variables: __FIRST__, __LAST__, __INNER__, __ODD__ inside your TMPL_IF or TMPL_UNLESS tags. To see what I mean, check out the template example at the bottom of this post.

    In particular, we care about the __ODD__ variable, which will be set to true on the odd numbered passes. By testing this variable, we can print either the <tr> or </tr> tags when appropriate. Consider the following code:

    #!/usr/bin/perl -w use strict; use HTML::Template; my @scores = ( { name => 'name1', score => 4 }, { name => 'name2', score => 2 }, { name => 'name3', score => 3 }, ); my $template = HTML::Template->new( filename => 'scores.tmpl', loop_context_vars => 1, ); $template->param(scores => \@scores); print $template->output;

    Which loads a template that contains the following text:

    <table> <TMPL_LOOP NAME='scores'> <TMPL_IF NAME='__ODD__'> <tr> </TMPL_IF> <td><TMPL_VAR NAME='name'></td><td><TMPL_VAR NAME='score'></td> <TMPL_UNLESS NAME='__ODD__'> </tr> </TMPL_UNLESS> </TMPL_LOOP> </table>

    This will iterate over the @scores and print them in two columns in the table. There is only one drawback to this approach, if the @scores has an odd number of elements, the final </tr> will not be printed. This can either be solved by pushing an empty element onto the array, or creative use of the __LAST__ and __ODD__ variables together. I personally prefer the latter and try to offload presentation logic off to the template, rather than pollute the code with special exceptions.

      Thanks! That's perfect. Well, almost. Perfect would include generalization to more than just two columns ;)

      When I first read your message, I kicked myself for not RTFM carefully. Then went back to the FM and couldn't find a reference to __ODD__. How odd! A quick search on CPAN brought enlightenment: { CPAN => 2.3, PPM => 1.8 }
      I'm going to have to start relying only on CPAN rather than using Active State for its convenience on windows.

      Off to search for ways to load pod docs into the pretty html format...


(jeffa) Re: HTML::Template - Two columns?
by jeffa (Bishop) on Jul 03, 2001 at 23:33 UTC
    Not especially pretty or Golf-savy, this should do the job:
    use strict; use HTML::Template; my @names = qw(name1 name2 name3); my @gpas = qw(4 2 3); my @struct; for (0..$#names) { push @struct, { NAME => @names[$_], GPA => @gpas[$_], }; } my $template = HTML::Template->new(filename => 'template'); $template->param(STUDENT => \@struct); print $template->output; <!-- template file --> <TMPL_LOOP NAME=STUDENT> Name: <TMPL_VAR NAME=NAME><br> GPA: <TMPL_VAR NAME=GPA><p> </TMPL_LOOP>
    wrong solution, move along - nothing to see here . . .



      Thanks, but no. That's similar to the current code. What I'd really like is:


      Template's implicit indexing of the array makes this more difficult than it might be.

      I could do

      [ oddName => xxx, oddScore => zzz, evenName => xxx, evenScore => ddd ] +
      but that doesn't seem elegant :)


Re: HTML::Template - Two columns?
by TheoPetersen (Priest) on Jul 04, 2001 at 00:37 UTC
    I did this using nested loops, but that means you'll need to transform your array into rows of columns as described in other replies.

    My code received a single array of products and turned it into rows of three product elements each. It works thusly:

    my @rows; while (@products) { push @rows, { 'loop_products' => [splice @products, 0, 3], }; } $template_body->param( loop_row => \@rows, );
    Then in your template, you loop through both arrays:
    <TMPL_LOOP NAME=loop_row> <TMPL_LOOP NAME=loop_products> Display one product here. </TMPL_LOOP> </TMPL_LOOP>
    Works fine if your columns flow across the row. Enjoy :)
Re: HTML::Template - Two columns?
by voyager (Friar) on Jul 03, 2001 at 23:28 UTC
    Depends how you want it: 1,2, 3,4, 5,6, etc. or 1,4, 2,5, 3,6, etc.

    First way, have your loop write two TDs, and on the second make sure you haven't gone past the end of your array.

    For the second, you'll be writing the i'th element in column one and the ($#array/2 + $i)'th element for the second column.

    Dealing with boundary conditions, rounding of integers, etc. is left as an exercise.

Re: HTML::Template - Two columns?
by tomhukins (Curate) on Jul 04, 2001 at 03:14 UTC

    I've been using HTML::Template for almost two years now, and I've encountered this problem, and others, several times.

    Those who have already answered your question have pointed out that there isn't a neat way of doing this. I've found HTML::Template's limitations frustrating, but that hasn't stopped me using the module. The great thing about HTML::Template is that non-programmers find it intuitive enough. Too many templating systems are great for programmers, but don't suit other members of a Web team.

    Admittedly one site I worked on would have been better suited to Template Toolkit, as it is based on complicated logic that doesn't fit with HTML::Template's philosophy. However, many Web applications I've developed fit well with simple looping and variable substitution: in such cases HTML::Template is a great way of keeping both desingers and programmers happy.

    I realise that this isn't a direct answer to your question, but I wanted to make a point: HTML::Template might not be complex enough allow programmers to do things as simply as they'd like, but in Web development it's tough to find a solution that everyone involved is happy with. I've found HTML::Template does a good job of keeping everyone relatively happy.

Re: HTML::Template - Two columns?
by AidanLee (Chaplain) on Jul 04, 2001 at 04:22 UTC

    Disclaimer: I have no experience with HTML::Template, but I thought I would bring up that generally the best way to try to divide things into even columns, IMHO, is to use the mod operator. You probably can't do someting like this in HTML::Template, but I thought it might be useful to someone. Here it is with dreaded HEREDOCs (NOT recommended):

    $i=0; #iterator $n=2; #the number of columns we want print <<XHTML; <table> <tr> XHTML while( grab each record ) { $i++; print '</tr><tr>' if not $n % $i; print <<XHTML; <td>Record Goes Here</td> XHTML } print <<XHTML; </tr> </table> XHTML
Re: HTML::Template - Two columns?
by hey_david (Sexton) on Jul 14, 2003 at 20:01 UTC
    I just posted a solution here.

    It allows you to choose the number of columns as well as the ordering of your data - either across or down the columns.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://93641]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2019-05-20 09:43 GMT
Find Nodes?
    Voting Booth?
    Do you enjoy 3D movies?

    Results (126 votes). Check out past polls.