[Petal] Reviving the Petal Cookbook
William McKee
william at knowmad.com
Fri Jan 14 19:49:45 GMT 2005
After Warren's excellent tips, I went digging around in the archives to
find the Cookbook.pod that I started (way back in September 2002). I've
added his two tips and reattached it to this message. I welcome your
suggestions and/or additions. It's missing more basic examples of usage
but my intention was to preserve some of the less obvious tricks as I
learn them. Perhaps over time others will contribute and make it a more
complete cookbook. Is there any interest in including this with the
Petal distribution?
William
--
Knowmad Services Inc.
http://www.knowmad.com
-------------- next part --------------
=head1 NAME
Petal::Cookbook - Recipes for building templates with Petal
=head1 SYNOPSIS
Not Applicable
=head1 DESCRIPTION
This document contains some examples of L<Petal|Petal> template usage.
=head1 NOTES
I tend to use Petal to generate HTML files from HTML templates. I name these templates with the .tmpl extension to help distinguish templates from static html. Nonetheless, the templates should be in a non-web accessible directory if you are using Petal for developing web applications.
=head1 BASICS
=head2 Passing a hashreference to Petal::process
An effective way to collate data to send to the Petal process command is via a hash reference. Used as follows, this technique allows you to build up your data to be passed to the template slowly:
my $hash = { object => $some_object, number => 3 };
$hash->{'foo'} = "bar";
my $template = new Petal ( 'test.tmpl' );
my $html = $template->process($hash);
# Output the results
print "Content-type: text/html\n\n";
print $html;
=head1 INTERMEDIATE TIPS
=head2 Assigning attributes (submitted by Warren Smith)
Up until now, if I wanted to use petal to pre-select an item in a selectbox, I
would have to do each item twice, like so:
<select>
<div petal:repeat="option options">
<option petal:condition="true: option/selected" petal:attributes="value option/value" petal:content="option/label" selected="selected">Option 1</option>
<option petal:condition="false: option/selected" petal:attributes="value option/value" petal:content="option/label">Option 2</option>
</div>
</select>
$VAR1 = [
{ value => 1, label => 'Option 1', selected => 1 },
{ value => 2, label => 'Option 2', selected => 0 },
{ value => 4, label => 'Option 3', selected => 0 },
];
After reading the Petal source, I found that if you use petal:attributes
to assign an attribute an undefined value, the attribute gets omitted,
thus the above code can be replaced with the simpler version below:
<select>
<option petal:attributes="value option/value; selected option/selected" petal:content="option/label">Option 1</option>
</select>
$VAR1 = [
{ value => 1, label => 'Option 1', selected => 1 },
{ value => 2, label => 'Option 2' },
{ value => 4, label => 'Option 3' },
];
It turns out that although not documented in Petal's documentation, this
behavior is part of the TAL specification:
http://www.zope.org/Wikis/DevSite/Projects/ZPT/TAL
Thanks to Warren Smith for this tip and Fergal Daly for his knowledge of the TAL specification.
=head2 Generating even/odd rows (submitted by Warren Smith)
I developed a decode: modifier that works similar to Oracle's decode
statement. It should be making it into the next release of Petal::Utils. So,
making even/odd rows of a table different classes, which allows you to do
things like alter color, font-size, etc, is relatively easy.
Example:
<table>
<tr class="decode: repeat/even 1 'even' 'odd'">...</tr>
</table>
Thanks to Warren Smith for this tip.
=head1 ADVANCED
=head2 Invoking methods on objects
Petal supports the ability to call an object's methods if passed in to Petal::process via the %hash. Say you wish to check whether a particular record is contained in a recordset returned from an SQL query. Using OO-Perl techniques, you could use the following technique as described by Jean-Michel:
* all your records are hashrefs which come from some database
* you have a list of them to display
Let's say that the database table looks like this:
Raters (id, first_name, last_name, relation, phone, email)
You could bless each record into a package as is:
use MyApplication::Record::Rater;
my @records = complicated_query_somewhere_else();
bless $_, "MyApplication::Record::Rater" for (@records);
Your module could look like that:
package MyApplication::Record::Rater;
use strict;
use warnings;
use CGI;
use Carp;
sub is_current_id
{
my $self = shift;
my $cgi = CGI->new;
my $id = $cgi->param ('rater.id');
return unless (defined $id and $id and $id =~ /^\d+$/);
return $id == $self->{id};
}
1;
Then on top of your existing data, you have a method which you can call
from Petal, i.e.
<span petal:condition="true:record/is_current_id">
blah blah blah...
</span>
This trick can also be used when you have foreign keys in database
fields.
<fictious_scenario>
For example, let's imagine that you have a column called
'friend_id'. It references another 'rater' which is supposed to be a
friend of that person.
You could defined the following subroutine:
# give me the friend record for that person
sub friend
{
my $self = shift;
my $friend_id = $self->{friend_id};
my $sql = 'select * from rater where id = ?';
my $sth = $::DBH_CONNECTION->prepare_cached ($sql);
$sth->execute ($friend_id);
my $hash = $sth->fetchrow_hashref;
return unless (defined $hash);
bless $hash, "MyApplication::Record::Rater";
return $hash;
}
Then in your template, you could do:
<?petal:if name="true:rater/friend"?>
Your friend is:
$encode:rater/friend/first_name
$encode:rater/friend/last_name
<?petal:end?>
</fictious_scenario>
Thanks to Jean-Michel Hiver for this tip.
NEEDS TO BE TESTED
NEEDS TO BE TESTED
=head2 Using CGI.pm to build forms
NEEDS TO BE TESTED
NEEDS TO BE TESTED
Be sure to call CGI with the -compile option as follows:
use CGI(-compile [:all]);
Calling the HTML generating methods of CGI.pm from the Petal template provides
an extremely simple means to develop forms. For example, the ususal ratnest of
loops used to populate a checkbox group can be replaced by the simple elegant
construct below. You can put in a dummy checkbox to give the HTML designer
something to look at.
<span petal:replace="query/checkbox_group 'Choices' choices '' 'true'">
<input name="Choices" type="checkbox" value="test">Test</input> </span>
Thanks to Kurt Stephens for this tip.
=head1 COPYRIGHT
Copyright (c) 2002-2005 Knowmad Services Inc. All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=head1 AUTHOR
William McKee <william at knowmad.com>.
=head1 SEE ALSO
L<Petal|Petal>, L<Petal::Utils|Petal::Utils>
=cut
More information about the Petal
mailing list