I have a currency value that I would like to format using Locale::Currency::Format however I have no idea how to format it.
Here is my output in Template Toolkit
[% amount %]
I would like this to be outputted using the following method:
currency_format('USD', amount, FMT_SYMBOL)
New to template toolkit so any help is appreciated.
I like Dave Cross' answer, and I agree with both he and codnodder about EVAL_PERL, which I've yet to find necessary as a solution in 7 or 8 years of almost daily TT use.
Personally, I would use:
[%- USE fmt = Class('Locale::Currency::Format'); -%]
<td>[% fmt.currency_format(var1, var2, var3) %]</td>
But if I was using this all the time, I'd be tempted to write a TT plugin wrapper around it.
I can't find Local::Currency::Format on CPAN, so I can't show you exactly how it works with this module. I can, however, show you the general direction you need to go in.
You have several options:
1/ Use currency_format to format the data before it is passed into the template.
my $amount = currency_format('USD', $amount, FMT_SYMBOL);
$tt->process($template_name, { amount => $amount, ... }) or die;
Then in the template you can just use [% amount %].
2/ Pass currency_format as a dynamic variable to the template.
$tt->process($template_name, {
amount => $amount,
currency_format = > \¤cy_format,
...
}) or die;
Then in the template, you can use currency_format as a function:
[% currency_format('USD', amount, FMT_SYMBOL) %]
3/ Write a real TT plugin for Local::Currency::Format.
If you have EVAL_PERL enabled in your "controller", you can use
embedded perl to include the module and add a vmethod for example.
E.g.,
use strict;
use Template;
my $tt = Template->new(EVAL_PERL=>1);
my $out;
$tt->process(\*DATA, { amount => 50.34 }, \$out) or die $tt->error, "\n";
print $out;
__DATA__
[% PERL -%]
sub dollars { sprintf('$%0.02f', $_[0]); }
# or:
# use Local::Currency::Format;
# sub dollars { currency_format('USD', $_[0], FMT_SYMBOL); }
$stash->define_vmethod('scalar', 'dollars', \&dollars);
[% END -%]
The amount is [% amount.dollars %].
If you have some access to the "controller", you can add a FILTER.
use strict;
use Template;
#use Local::Currency::Format;
my $tt = Template->new({
#FILTERS => { 'dollars' => sub { currency_format('USD', $_[0], FMT_SYMBOL); } },
FILTERS => { 'dollars' => sub { sprintf('$%0.02f', $_[0]); } },
});
my $out;
$tt->process(\*DATA, { amount => 50.34 }, \$out) or die $tt->error, "\n";
print $out;
__DATA__
The amount is [% amount | dollars %].
EDIT: Note that my use of sprintf to format the currency is just a placeholder. You would replace that with whatever module or method you choose.
Related
I would like to use the current C version of Fletcher Penny's Multi-markdown as a filter in Template Toolkit. It's not clear to me how to set this up.
At present I'm not calling TT as a module, but simply writing templates that are called with tpage and ttree.
Template-Toolkit filters are actually quite easy to write.
Module:
package Template::Plugin::Filter::MultiMarkdown;
use strict;
use warnings;
our #ISA = 'Template::Plugin::Filter';
sub init {
my $self = shift;
$self->install_filter('markdown');
return $self;
}
sub filter {
my ($self, $text) = #_;
... Code that transforms $text and returns the transformed text ...
}
1;
Usage:
[% USE Filter.MultiMarkdown %]
[% FILTER markdown %]...[% END %]
-or-
[% ... | markdown %]
How its being declared:
my $HTML_GRABBER = HTML::Parser->new('api_version' => 2,
'handlers' => {
'start' => [\&start_tag,"tagname,text"],
'text' => [\&read_text,"tagname, text"],
'end' => [\&end_tag,"tagname"]
}
);
callback function:
sub read_text {
print Dumper(#_);
die "\n";
my ($tag,$stuff) = #_;
if(($DO_NOTHING==0)&&($tag eq $current_tag))
{
push #{$data_queue}, $stuff;
}
}
result:
$VAR1 = undef;
$VAR2 = '
';
so it passes an undefined value and an empty string for tag and text, apparently. THis is reading from a saved HTML file on my harddrive. IDK
I had something like this in mind:
#DOC structure:
#(
# "title"=> {"text"=>#("text")}
# "div" => [
# {
# "p"=> [
# {
# "class" => string
# "id" => string
# "style" => string
# "data"=>["first line", "second line"]
# }
# ],
# "class" => string
# "id" => string
# "style" => string
# }
# ]
#)
You've told it to.
You specified which parameters should be passed to the text handler:
'text' => [\&read_text,"tagname, text"],
Well, there is no tagname for a text token, and therefore it passes you undef as the first paramter.
What exactly are you trying to do? If you describe your actual goal, we might be able to suggest a better solution instead of just pointing out the flaws in your current implementation. Check out: What is an XY Problem?
Addendum about Mojo::DOM
There are modern modules like Mojo::DOM that are much better for navigating a document structure and finding specific data. Check out Mojocast Episode 5 for a helpful 8 minute introductory video.
You appear to be prematurely worried about efficiency of the parse. Initially, I'd advise you to just store the raw html in the database, and reparse it whenever you need to pull new information.
If you Benchmark and decide this is too slow, then you can use Storable to save a serialized copy of the parsed $dom object. However, this should definitely be in addition to the saved html.
use strict;
use warnings;
use Mojo::DOM;
use Storable qw(freeze thaw);
my $dom = Mojo::DOM->new(do {local $/; <DATA>});
# Serializing to memory - Can then put it into a DB if you want
my $serialized = freeze $dom;
my $newdom = thaw($serialized);
# Load Title from Serialized dom
print $newdom->find('title')->text;
__DATA__
<html>
<head><title>My Title</title></head>
<body>
<h1>My Header one</h1>
<p>My Paragraph One</p>
<p>My Paragraph Two</p>
</body>
</html>
Outputs:
My Title
I have perl generating a list through Template Toolkit.
How do I add a couple of single non-list variables into the mix, e.g. to include outside of the FOREACH within the .tt2 file?
my $e = {
};
for my $c (sort keys %$cat) {
push #{$e->{categories}},
{
name => $c,
url => "$c"
};
}
$template->process('main.tt2', $e, "index.html") or die;
<ul>
[% FOREACH c IN categories -%]
<li>[% c.name %]</li>
[% END %]
</ul>
$e->{somethingElse} = "some value";
and
[% somethingElse | html %]
I want to use a constant in my TT template. In HTML::Mason (my previous templating engine of choice) I could do:
<%once>
use MyApp::Constants qw(CONSTANT);
</%once>
How can I do this in Template Toolkit? As mentioned in the title this is a Catalyst app so I was thinking I could put the constants in the stash but that seems a bit awkward.
--edit
Sorry - I should have mentioned I want to use my own constants - exported from MyApp::Constants, without duplication.
In your TT configuration, you can use the VARIABLES option to pass a list of values that will be passed to every template when it's processed. Using some symbol table trickery, you can suck out all your constants into the config:
use MyApp::Constants;
use Template;
my $tt; # template object
{
no strict 'refs';
$tt = Template->new( {
VARIABLES => { map { $_ => &{ 'MyApp::Constants::' . $_ } }
grep { defined &{ 'MyApp::Constants::' . $_ } }
keys %MyApp::Constants::
}
}
)
}
This looks at all the symbols in the package MyApp::Constants, checks if they are defined as subroutines (this is what constant.pm does under the hood) and then uses map to provide a hashref of them to TT.
Several possibilities.
Just define some variables:
[% users = {
tom => 'Thomas',
dick => 'Richard',
larry => 'Lawrence',
}
%]
[% FOREACH u IN users %]
* [% u.key %] : [% u.value %]
[% END %]
Use the global variable:
[% global.version=1.234 %]
This is Version [% global.version %].
The META directive allows simple
metadata items to be defined within a
template. These are evaluated when the
template is parsed and as such may
only contain simple values (e.g. it's
not possible to interpolate other
variables values into META variables).
[% META
title = 'The Cat in the Hat'
author = 'Dr. Seuss'
version = 1.23
%]
As you already mentioned in the question body, there's also this:
http://template-toolkit.org/docs/manual/Variables.html#section_Compile_Time_Constant_Folding
I have some strings that I am pulling out of a database and I would like to use Template Toolkit on them, but I can't seem to figure out how to use strings as TT input. Any tips?
Thanks!
-fREW
The documentation explains:
process($template, \%vars, $output, %options)
The process() method is called to process a template. The first parameter indicates the input template as one of: a filename relative to INCLUDE_PATH, if defined; a reference to a text string containing the template text; ...
# text reference
$tt->process(\$text)
|| die $tt->error(), "\n"
From the docs:
# text reference
$text = "[% INCLUDE header %]\nHello world!\n[% INCLUDE footer %]";
$tt->process(\$text)
|| die $tt->error(), "\n";
(Looks like I should have refreshed the page before posting.)
You may find String::TT as a nicer alternative way of doing it. Some teasers from the pod...
use String::TT qw/tt strip/;
sub foo {
my $self = shift;
return tt 'my name is [% self.name %]!';
}
sub bar {
my #args = #_;
return strip tt q{
Args: [% args_a.join(",") %]
}
}
and...
my $scalar = 'scalar';
my #array = qw/array goes here/;
my %hash = ( hashes => 'are fun' );
tt '[% scalar %] [% scalar_s %] [% array_a %] [% hash_h %]';