Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^3: Preparing data for Template

by pryrt (Abbot)
on Dec 31, 2020 at 00:51 UTC ( [id://11126022]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Preparing data for Template
in thread Preparing data for Template

In the example code, get_user_projects doesn't seem to be explicitly called.

Not in the Perl. But in the template, the line [% FOREACH project IN worklist(me.id) %] calls worklist as a function with the appropriate ID as its argument.

I would assume that in your code, if you don't change to 'frames' => list_frames() (as already suggested), then you would need to call the frames as a function rather than treating it as a variable: probably like [% FOREACH frame IN frames() %] (untested)

(But it seems to me that you shouldn't need to call a function from the template, unless the data will change based on some parameter from the template, like the me.id argument in the tutorial example. Since you're not feeding anything back to the function, why not just define frames as the arrayref rather than the coderef?)

Replies are listed 'Best First'.
Re^4: Preparing data for Template
by Bod (Parson) on Dec 31, 2020 at 11:05 UTC
    Not in the Perl. But in the template, the line [% FOREACH project IN worklist(me.id) %] calls worklist as a function with the appropriate ID as its argument.

    That confirms what I suspected - thanks

    (But it seems to me that you shouldn't need to call a function from the template, unless the data will change based on some parameter from the template, like the me.id argument in the tutorial example. Since you're not feeding anything back to the function, why not just define frames as the arrayref rather than the coderef?)

    This is a learning exercise rather than a complete solution. Totally agreed that a function is not needed here yet, but I'm trying to learn how to use functions within Templates so that, when I need them, I have a good grasp of how to implement them.

    Update:

    probably like [% FOREACH frame IN frames() %] (untested)

    Yes - that is the part I omitted...thanks, that gets me further.
    The subroutine is now being called. However, the values are not being passed back to the Template. Or, if they are, they are not getting displayed.

      However, the values are not being passed back to the Template. Or, if they are, they are not getting displayed.

      Here is an SSCCE to demonstrate looping over the return values:

      #!/usr/bin/env perl use strict; use warnings; use Template; sub baz { return qw/there World/; } my $v = { bar => \&baz }; my $t = join '', <DATA>; Template->new->process (\$t, $v); __DATA__ [% FOREACH foo IN bar() %] Hello [% foo %]! [% END %]

      🦛

        Thanks hippo.
        Based on your code sample and what I already have, I have built a test which shows it is not the way I am using Template that is the issue - it is my display() function. In the 'real' code this is abstracted into a Site::HTML module because I want to hide the site variables away in a separate module with only Site::HTML and Site::Common having access to it - perhaps I need to rethink that design.

        use Template; use strict; my $template = Template->new; my $vars = { 'frames' => \&get_frames }; $template->process('test.tt', $vars); # this works display('test', $vars); # this doesn't sub get_frames { my @list; foreach my $l( qw/first second/ ) { my $fr = { 'one' => $l, 'two' => $l, }; push @list, $fr; } return @list; } sub display { # my $self = shift; my $file = shift; my %vars = @_; $template->process("$file.tt", \%vars); }

        update

        The test Template...

        Start test... [% FOREACH frame IN frames() %] Frame - [% frame.one %] [% frame.two %] [% END %] End test...

      Does this journey tell you anything about the advisability of mixing presentation and code in this fashion? This sort of popping back and forth between presentation and code makes for maintenance headaches. It's also a great temptation with Template Toolkit. For something simple like populating a list with HTML::Template you can:

      use strict; use warnings; use HTML::Template; my @items = map {{item => $_}} qw(first second third fourth); my $template = HTML::Template->new(filehandle => *DATA); $template->param(items => \@items); print $template->output(); __DATA__ <TMPL_IF name="items"> <ul><TMPL_LOOP name="items"> <li><TMPL_VAR name="item"></li></TMPL_LOOP> </ul></TMPL_IF>

      Prints:

      <ul> <li>first</li> <li>second</li> <li>third</li> <li>fourth</li> </ul>

      and renders as:

      • first
      • second
      • third
      • fourth
      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
        Does this journey tell you anything about the advisability of mixing presentation and code in this fashion?

        Mixing presentation and code is exactly what I am trying to avoid.
        The 'real' code will have multiple values pulled from the backend DB, not just one value which is why I put them in an anonymous hash. Having said that, for this part of the code at least, the values will be static in the sense that they won't change during the runtime so having Template call a function won't be necessary.

        I think perhaps I need to do some more studying of the different kinds of loop that Template offers. Already I have changed quite a bit of what I have written so that one template file includes another instead of having the code process each separately...so much to learn!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11126022]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-20 02:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found