Display array in multi-column table using template tookit? - perl

I have an array of phone numbers. I want to display these numbers in a table, 5 numbers per row. Can I do this in Template Toolkit without modifying my data structure?

You can use the plugin Template::Plugin::Table:
[% USE table(phone_numbers, cols=5) %]
[% FOREACH row IN table.rows %]
[% FOREACH item IN row %]
[% item %]
[% END %]
[% END %]
phone_numbers is a reference to the phone number array which should be passed to Template Toolkit. Example:
...
$data->{phone_numbers} = \#phone_numbers;
$template->process('example.tmpl', $data)
|| die "Template processing failed: ", $template->error(), "\n";

Related

How to join lists (references) into a single one

I have 2 lists with complex (similar) hashes in them and i want to iterate over both lists within a single loop to not duplicate the code (I also do not want to make a block or macro)
testList1 = [0,1,2,3,4,5];
testList2 = [6,7,8,9,10,];
FOREACH item IN [testList1 , testList2]; # <--- ???
doSomething = doSomething _ 'useful ' _ item;
END;
The above statement creates a new list that contains only the references to the lists, but i want a temporary list with their contents.
How can i achieve this without extra manual list building logic. Is there some construct?
The list VMethod merge() will do the job:
[% testList1 = [0,1,2,3,4,5] %]
[% testList2 = [6,7,8,9,10,] %]
[% doSomething = '' %]
[% FOREACH item IN testList1.merge(testList2) %]
[% doSomething = doSomething _ 'useful ' _ item %]
[% END %]
[% doSomething %]
See http://www.template-toolkit.org/docs/manual/VMethods.html#section_merge for more information.

Text::Xslate returning incorrect value for function call

I'm using Text::Xslate with HTML::FormHandler (HTML::FormHandler is actually used behind the scenes by CatalystX::SimpleLogin, in case that helps). I'm using Text::Xslate's TTerse syntax and trying to show the errors in my template like so:
[% FOR field IN login_form.error_fields %]
[% FOR error IN field.errors %]
<p>[% field.label _ ': ' _ error %]</p>
[% END %]
[% END %]
If I just print out
[% login_form %]
It returns CatalystX::SimpleLogin::Form::Login=HASH(0x7fbb21722a20), which is what I would expect. But then when I call error_fields on it, it just returns a 1. However, when I use Template::Toolkit instead of Text::Xslate, this works properly and the errors show. Does anyone know why error_fields is returning a number and not an array?

how to check whether an element is present in an array using template toolkit

i am trying to find out whether an array contains an element in template toolkit. not sure how? can anyone help?
my $var ={
myarray => ['a','c','b','d']
}
passed to tt:
now want to check:
[% IF ( myarray contains 'a') %]
[% END %]
[% IF ( myarray contains 'e') %]
[% END %]
grep
Returns a list of the items in the list that match a regular expression pattern.
Therefore,
[% IF myarray.grep('^e\z').size %]
<p>Hello World</p>
[% END %]
myarray = ['17', '177', '166']
value = 16
[% IF myarray.grep('^$value$').size %] # will be true
<p>Hello World</p>
[% END %]
myarray.grep('^$value$') # return ['166']
another way
[% IF myarray.grep('^$value$').0 == value %] # will be false
<p>Hello World</p>
[% END %]

error in printing data using template module

I have little problem with printing data like this, I have written script like this
[% FOREACH comp IN company %]
[% comp.name %]
[% comp.location%]
employeedata:
[% FOREACH employee IN comp.domain.java.employee %]
[% FOREACH experiance IN employee.experiance %]
[% FOREACH obj IN ObjectDefinition%]
[% FOREACH beha IN obj.experiance %]
[% IF beha.years == experiance.years %]
[% beha.Name %],
[% LAST %]
[% END %]
[% END %]
[% END %]
[% END %]
[% END %]
[% END %]
from above script comparing "years" value in two keys in a hash and if both are same print the employee name. Its working and it printing like this as show below.
if three names is there it printing like this.
clar, larson, per,
if two names is there it printing like this.
clar, larson,
but I need to print like this
if three names is there
clar, larson or per.
if two names is there like this
clar, larson.
if only one name is there like this
clar.
I have maximum number of names is three only. I need to print like this help me how to print like this. if any mistakes is there excuse me please.
I tried like this also
[% FOREACH employee IN comp.domain.java.employee %]
[% FOREACH experience IN employee.experience %]
[% FOREACH obj IN ObjectDefinition%]
[% FOREACH beha IN obj.experience %]
[% IF beha.years == experience.years %]
[% IF employee.experience.size == 1 %]
[% beha.Name %].
[% ELSIF employee.experience.size == 2 %]
[% beha.Name %],[% beha.Name %].
[% ELSIF employee.experience.size == 3 %]
[% beha.Name %],[% beha.Name %]or[% beha.Name %].
[% END %]
[% END %]
[% END %]
[% END %]
[% END %]
[% END %]
but it printing when we have one name. if we have two names it printing like this
clar,clar.
larson,larson.
if we have three names it printing like this
clar,clar or clar.
larson,larson or larson.
per,per or per.
what is wrong with my script I cant solve this problem can any body help me please.
The second attempt is definitely closer to what you're going to need. But the order of the loops doesn't look right. beha.Name is only ever going to have the value of the current record.
I think you want something like this:
[% SET staff = []; # empty list
FOREACH beha IN obj.experience;
staff.push(beha) IF beha.years == experience.years;
END; %]
[% IF staff.size == 1;
staff.0.Name;
ELSIF staff.size == 2;
"$staff.0.Name, $staff.1.Name";
ELSIF staff.size >= 3;
"$staff.0.Name, $staff.1.Name or $staff.2.Name";
END %]
The IF-ELSIF loop is not very pretty, but there's no obvious staff.join() construction that's going to do what you need with that mix of commas and text separators and a limit of 3 elements.
UPDATE
As requested, an example using .join:
If you had an arbitrary length list of names, you might want to present them as name, name, [name, ...] or name:
ELSIF staff.size >= 3;
SET lastname = staff.pop; #remove last person from list
staff.join(', '); " or $lastname";
END;
But as I said previously, with a maximum of 3 names, this is overkill.

how to printing data with template module

My English is little bit poor so don't hesitate me if didn't understand.
I have problem with perl template tool kit module. This is my first experience using this module.I am reading xml data from file and I used XML::Simple(ForceArray) to parse and DATA::Dumper to print. Printing data is
$var1={
'data'=>{
'employee'=>[
{
'name'=>'suraj',
'number'=>'f11a0478',
'adress'=>' badvel,kadapa,a.p,india',
},
{
'name'=>'misra',
'number'=>'047902',
'adress'=>' raipur,ananthapur,a.p,india',
}...........
...........
],
'company'=>{
'name'=>'bosch',
'location'=>'banglore',
'domain'=>{
'java'=>{
'employee'=>[
{
'name'=>'suraj',
'number'=>'f11a0478',
'experience'=>{
'years'=>'3',
'projects'=>'4',
}
},
{
'name'=>'misra',
'number'=>'047902',
'experience'=>[
{
'years'=>'1',
'projects'=>'1',
},
{
'years'=>'1',
'projects'=>'1',
}
]
},
]
}
}................
.................
};
I used template toolkit process like this and printed in some file, I written code like this
[% FOREACH comp IN company %]
[% comp.name %]
[% comp.location%]
employeedata:
[% FOREACH employee IN comp.domain.java.employee %]
employee name: [% employee.name +%] numb [%+ employee.number %]
[% FOREACH experience IN employee. experience %]
[% experience.years %]
[% experience.projects %]
[% END %]
[% END %]
[% END %]
From above script I am able to print company employee, name, number, experience, years ,projects. But my problem is I need to add address of employee also to this information. I am printing all information in company node and for all company's. But Address is located some other key in the hash. By using employee name and number(some employee having same name some having same number) I need to find the address and print the address in the employee details. help me with this problem. What should I do now, how to solve this problem.
You could do:
[% FOREACH de IN data.employee %]
[% IF de.name == employee.name && de.number == employee.number %]
[% de.address %]
[% LAST %]
[% END %]
[% END %]
I'd recommend doing something about the data structure before processing it with TT though, because this isn't very efficient. If comp.domain.java.employee and data.employee contains the same number of elements it's pretty straight forward.
EDIT: What I meant in my comment below is
[% FOREACH employee IN comp.domain.java.employee %]
[% addresses = [] %]
[% FOREACH de IN data.employee %]
<!-- Name, experience etc. -->
<!-- Then new address stuff: -->
[% IF de.name == employee.name || de.number == employee.number %]
[% addresses.push(de.address) %]
[% END %]
[% END %]
[% addressStr = addresses.join(', '); addressStr.replace(', ([^,]+)$', ' or $1') %]
[% addressStr %]
[% END %]
That's not printing addresses like address1, address2 or address3?