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

Hello all,
I'm having some trouble with HTML::Template giving me erroneous messages becaues the data I am passing to my methods isn't in arrayref form.
My code:
package PL::Template; use strict; use CGI; use HTML::Template; my $q = CGI->new; sub new { my $class = shift; my $self = {}; $self->{template}; $self->{content}; bless $self, $class; return $self; } sub format { my $self = shift; my %params = @_; $self->{content} = $params{content}; my $filter = sub { my $ref = shift; $$ref =~ s/\[aim:\/\/(.*?)\]/<a href="aim:username=$1">$1<\/a>/g; $$ref =~ s/\[google:\/\/(.*?)\]/<a href="http:\/\/www.google.com\ +/search\?q=$1">$1<\/a>/g; $$ref =~ s/\[email:\/\/(.*?)\]/<a href="mailto:$1">$1<\/a>/g; $$ref =~ s!\[([^|\]]+)\|([^\]]+?)\]!<a href=$1>$2</a>!gs; $$ref =~ s|\[([^\]]+?)\]|<a href=$1>$1</a>|g; }; my $tmpl= HTML::Template->new( filename => "tmpl/main.tmpl", associate =>$q, loop_context_vars =>1, global_vars=>1, filter => $filter ); $tmpl->param( %{ $self->{content} } ); return $q->header, $tmpl->output(); } sub output { my $self = shift; return $self->format; } 1; ##index.cgi #!perl -w use strict; use PL; my $obj = PL->new; my %content = ( title=>'hi', body=>'hello testing' ); my $page = $obj->Template->format (content => \%content); print $obj->Template->output; ##the template <html> <head> <title><!--TMPL_VAR name="title"--></title> </head> <body> <!--TMPL_VAR name="body"--> </body> </html> </readmore> <br /> I have attempted numerous methods of formatting my data into an arrayr +ef, only one of which has worked: <code> $tmpl->param( content => [{ title=>'hi'...body=>'testing' }] );

now as simple as this seems, I can't get my content variable in the correct arrayref format.
HTML::Template says in the docs:
The <TMPL_LOOP> tag is a bit more complicated than <TMPL_VAR>. The <TMPL_LOOP> tag allows you to delimit a section of text and give it a name. Inside this named loop you place <TMPL_VAR>s. Now you pass to param() a list (an array ref) of parameter assignments (hash refs) for this loop. The loop iterates over the list and produces output from the text block for each pass. Unset parameters are skipped. Here's an example: In the template: <TMPL_LOOP NAME=EMPLOYEE_INFO> Name: <TMPL_VAR NAME=NAME>
Job: <TMPL_VAR NAME=JOB>

</TMPL_LOOP> In the script: $template->param(EMPLOYEE_INFO => { name => 'Sam', job => 'programmer' }, { name => 'Steve', job => 'soda jerk' }, ); print $template->output(); The output in a browser: Name: Sam Job: programmer Name: Steve Job: soda jerk
Any ideas?
Thanks in advance.

meh.

Replies are listed 'Best First'.
Re: HTML::Template data types problem
by blokhead (Monsignor) on Apr 21, 2005 at 04:10 UTC
    I really don't understand why you need a TMPL_LOOP. Maybe I'm jumping to wild conclusions here, but I wonder if you're being sidetracked by the line of POD which says:
    The <TMPL_LOOP> tag allows you to delimit a section of text and give it a name.
    While this is technically true in some sense, the more important purpose of a TMPL_LOOP is to delimit a section of the template which is to be repeated a variable number of times (thus the name LOOP), with different values filled into its constituent TMPL_VARs on each iteration (and the results all concatenated together).

    In other words, if you have a TMPL_LOOP called 'foo', you must assign to the template's 'foo' param an arrayref of things. Each of these things is a hashref of params to use for each iteration when repeatedly filling out the stuff within the TMPL_LOOP (think of HTML::Template recursing multiple times at this point, using only the template text within the TMPL_LOOP section, and calling param using the contents of each hashref). Given the template you provided, I doubt this is what you want -- multiple <body> and <title> tags in your HTML output?

    It seems like you grouped the template data in your object's implementation (which is a good idea) by putting them all in a secondary hash called 'content', and then you tried to apply the same named encapsulation to the parts of template. This is not really a great idea here -- HTML::Template doesn't provide a primitive way to do this. Plus, you were just sectioning off pretty much the entire template.

    Instead, you can get rid of the TMPL_LOOP from the template, and simply say:

    $tmpl->param( title => $self->{content}{title}, body => $self->{content}{body} );
    Or even
    $tmpl->param( %{ $self->{content} } );
    Save TMPL_LOOP for when you have a list of things to display in the template, whose length may vary.. Then when you do use a TMPL_LOOP, its param needs to be assigned an arrayref of hashrefs (not a hashref like $self->{content} as you were using before).

    blokhead

Re: HTML::Template data types problem
by friedo (Prior) on Apr 21, 2005 at 02:35 UTC
    my %content = { title => 'hi', body=>'testing' }; my $page = $obj->Template->format (content => %content);

    This assigns an anonymous hash reference to a hash. If you had warnings on, you would see: "Reference found where even-sized list expected" in your error log. You probably want to do something like this:

    my $content = { title => 'hi', body => 'testing' }; my $page = $obj->Template->format( content => $content );

    A TMPL_LOOP expects an array of hash references. So in your format method, you'll need to stick the hashref inside an array. But based on what you posted, it doesn't look like you ever attempt to shift the hashref off of @_, you just pass $self->{content} to the template. That just contains an empty array reference.

Re: HTML::Template data types problem
by Cody Pendant (Prior) on Apr 21, 2005 at 04:13 UTC
    I'm having some trouble with HTML::Template giving me erroneous messages becaues the data I am passing to my methods isn't in arrayref form.

    But you never actually mention the error message you get and why you think it's erroneous!



    ($_='kkvvttuu bbooppuuiiffss qqffssmm iibbddllffss')
    =~y~b-v~a-z~s; print
Re: HTML::Template data types problem
by kprasanna_79 (Hermit) on Apr 21, 2005 at 05:36 UTC
    Hai,
    $tmpl->param( content => [{ title=>'hi'...body=>'testing' }] );
    U have used this way.
    But try this way, which always works for us.
    push(@array, { title=>'hi',body=>'testing'}); $tmpl->param( content => \@array);
    U can use this logic to solve the issue...alter accordingly..
    prasanna.k
Re: HTML::Template data types problem
by stonecolddevin (Parson) on Apr 21, 2005 at 21:32 UTC
    Well, I found a working solution, I'm not sure if it's the BEST idea but it works with all my other methods:
    if (@_) { $self->{content} = shift;}
    Like friedo said, I should shift off the content from @_;
    meh.