How to sum organized array in php twig? - twig

I want to sum array in twig which has similar name. I have tried following but stuck how to sum the array.
{% for job in jobs %}
{% if not attribute(output, job.getJobName()) is defined %}
{% set output = output|merge({ (job.getJobName()) : {}, }) %}
{% endif %}
{% set output = output|merge({(job.getJobName()) : output[job.getJobName()] | merge([job,])}) %}
{% endfor %}
{% for group_title, items in output %}
<tr>
<td>{{ job_name }}</td>
<td></td>
<td></td>
<td></td>
<td>Total Salary</td>
<td>{{ total_salary }}</td> //how to get total salary
</tr>
{% for item in items %}
{% if (item) %}
<tr>
<td>{{ item.getEmpName() }}</td>
<td>{{ item.getEmpSalary() }}</td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
On Dump this are the arrays
array:21 [▼
0 => Model\JobItem {#3330 ▶}
1 => Model\JobItem {#3336 ▶}
2 => Model\JobItem {#3341 ▶}
3 => Model\JobItem {#3584 ▶}
4 => Model\JobItem {#3320 ▶}
5 => Model\JobItem {#3314 ▶}
6 => Model\JobItem {#3309 ▶}
7 => Model\JobItem {#3303 ▶}
8 => Model\JobItem {#3298 ▶}
9 => Model\JobItem {#3292 ▶}
10 => Model\JobItem {#3288 ▶}
11 => Model\JobItem {#2845 ▶}
12 => Model\JobItem {#2728 ▶}
13 => Model\JobItem {#2722 ▶}
14 => Model\JobItem {#2996 ▶}
15 => Model\JobItem {#3004 ▶}
16 => Model\JobItem {#2746 ▶}
17 => Model\JobItem {#2751 ▶}
18 => Model\JobItem {#2756 ▶}
19 => Model\JobItem {#2765 ▶}
20 => Model\JobItem {#2842 ▶}
]
array:2 [▼
0 => Model\JobItem {#2858 ▶}
1 => Model\JobItem {#2863 ▶}
]
What I want to achieve here is how to get total salary from each array?

Just loop the items another time and add all the salaries
{% for group_title, items in output %}
{% set total_salary = 0.00 %}
{% for item in items %}
{% set total_salary = total_salary + item.getEmpSalary() %}
{% endfor %}
<tr>
<td>{{ job_name }}</td>
<td></td>
<td></td>
<td></td>
<td>Total Salary</td>
<td>{{ total_salary }}</td> //how to get total salary
</tr>
{% for item in items %}
{% if (item) %}
<tr>
<td>{{ item.getEmpName() }}</td>
<td>{{ item.getEmpSalary() }}</td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}

Related

flask jinja2 variable of variable

I am trying to access a variable of a object in jinja2 using this code:
{% for row in rows.items %}
<tr>
{% for column in model_settings['table_columns'] %}
<td>
<p>{{ row.column }}</p>
</td>
{% endfor %}
</tr>
{% endfor %}
what I want is if column was username I would want it to give me
row.username. sorry for the bad explanation.
Jinja2 has the builtin attr filter to access an attribute of an object. The name of the attribute can be a static string, or in your case: a string stored in a variable:
{% for row in rows.items %}
<tr>
{% for column in model_settings['table_columns'] %}
<td>
<p>{{ row|attr(column) }}</p>
</td>
{% endfor %}
</tr>
{% endfor %}

Twig table issues using craftcms

I am new to craft and twig and am trying to access table values inside of a neo matrix and started running into some blockers. I don't know how to query the values properly I think. Here is my code:
{% if row.tableColumn|length %}
<table>
{% set policyTable = row.tableColumn.all() %}
{{ dump(row.tableColumn.all()) }}
{% for row in policyTable %}
<thead>
<tr>
<th>
{{ row.col1 }}
</th>
</tr>
<tr>
<td>
{{ row.column1 }}
</td>
</tr>
</thead>
{% endfor %}
</table>
{% endif %}
And here is the dump for reference (shortened):
array(1) { [0]=> object(craft\elements\MatrixBlock)#2695 (67)
{["genericRichTextOnlyListItems"]=> NULL ["tableColumn"]=> string(402)
"[{"col1":"THEAD1","col2":"THEAD2","col3":"THEAD3","col4":"THEAD4"},{"col1":"ROW1","col2":"60-75","col3":"15-30","col4":"5-20"},{"col1":"ROW2","col2":"45-55","col3":"35-45","col4":"5-20"},{"col1":"ROW3","col2":"5-15","col3":"75-85","col4":"15-25"}]"
} }
I am trying to access col1 in tableColumn which I have named column1 on the craft backend. {{ row.col1 }} and {{ row.column1 }} will not work. Any tips?
Looks like policyTable is an array of Matrix Blocks. Each array item (though there's only one) has the table columns under the key tableColumn, so you can try something like this (I renamed policyTable to policyTables since it's an array):
{% if row.tableColumn|length %}
<table>
{% set policyTables = row.tableColumn.all() %}
{% for row in policyTables[0].tableColumn %}
<thead>
<tr>
<th>
{{ row.col1 }}
</th>
</tr>
<tr>
<td>
{{ row.col2 }}
</td>
</tr>
<!-- etc. -->
</thead>
{% endfor %}
</table>
{% endif %}
Or if it's possible that there's more than one matrix block, you could try something like this:
{% if row.tableColumn|length %}
{% set policyTables = row.tableColumn.all() %}
{% for table in policyTables %}
<table>
{% for row in table.tableColumn %}
<thead>
<tr>
<th>
{{ row.col1 }}
</th>
</tr>
<tr>
<td>
{{ row.col2 }}
</td>
</tr>
<!-- etc. -->
</thead>
{% endfor %}
</table>
{% endfor %}
{% endif %}
In both cases, you probably want to handle the first row differently since it seems to be the heading row. You can utilize Twig's loop variable for this. (There might be some other ways as well.)

Iterating over key-value arrays in Twig?

I'm (finally) switching my site from Drupal7 to Symfony3.
I'm working on migrating my layout to .twig.
I've got a question about loops and key-value arrays.
I've configured a k/v array
{% set test = {
sec1: {
title: "title 1",
content: "content 1"
},
sec2: {
title: "title 2",
content: "content 2"
},
}
%}
I can reference any specific array element in other markup. E.g., this works as intended
<ul>
<li>
<h1>{{ test.sec1.title }}</h1>
<div>
<p>{{ test.sec1.content }}</p>
</div>
</li>
</ul>
Now I want to loop/repeat the block over a count of n. But trying this,
<ul>
{% for i in 1..5 %}
<li>
<h1>{{ test.sec{{ i }}.title }}</h1>
<div>
<p>{{ test.sec{{ i }}.content }}</p>
</div>
</li>
{% endfor %}
</ul>
fires an error
Unexpected token "punctuation" of value "{" ("end of print statement" expected) in default/index.html.twig at line 67.
500 Internal Server Error - Twig_Error_Syntax
I've been working with variations of these
http://twig.sensiolabs.org/doc/tags/for.html#iterating-over-keys
but can't get anything to work yet.
What's the right way to loop this list over the secN's in the key-value array?
The reason why your script does not work is that you cannot compose an object-property accessor like this.
What you probably need is iterating over a subset:
{% for sec in test|slice(0, 5) %}
{{ sec.title }}
{% endfor %}
Or, if you do indeed need access to the key: iteration over key and value:
{% for key, sec in test %}
{{ sec.title }}
{{key}}
{% endfor %}
If you need to slice while still accessing the key, you could combine the latter with a check to the loop variables:
{% for key, sec in test %}
{% if loop.index0 < 5 %}
{{ sec.title }}
{{key}}
{% endif %}
{% endfor %}
{% for key, item in content.field_invoice_no if key|first != '#' %}
<tr>
<td>{{ item }}</td>
<td> {{ content.field_invoice_date[key] }} </td>
</tr>
{% endfor %}
Iterating over key-value arrays in Twig
for reference entity code below
{% for key, item1 in node.field_quotation.entity.field_product %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ item1.entity.body.value |raw }}</td>
<td> {{ item1.entity.field_product_unit_required.value }}</td>
<td>{{ item1.entity.field_hsn_code.value }}</td>
<td>{{item1.entity.field_pro.number|number_format(2, '.', ',')}}</td>
{% endfor %}
</tr>

Twig - Fill a table horizontally with HTML2PDF

I'm working on filling a table horizontally in Twig and transform this twig view into a PDF.
I succeeded in filling it horizontally but I have an annoying problem remaining : I have a black line on the right of the last page of my resulting PDF.
Here's an picture of the problem in the PDF :
In Twig view :
Here's my code :
<table align="center">
<thead>
<tr>
<th>Numéro</th>
<th>Note</th>
<th>Classement</th>
<th class="espace"></th>
<th>Numéro</th>
<th>Note</th>
<th>Classement</th>
</tr>
</thead>
<tbody>
{% for passercolle in passercolles %}
{% if (loop.index is odd) or loop.first %}
<tr>
{% endif %}
{% if loop.index is odd %}
<td>{{ passercolle.username }}</td>
<td>{{ passercolle.note }}/20</td>
<td>{{ passercolle.classement }}</td>
<td class="espace" ></td>
{% elseif loop.index is even %}
<td>{{ passercolle.username }}</td>
<td>{{ passercolle.note }}/20</td>
<td>{{ passercolle.classement }}</td>
{% endif %}
{% if loop.last and loop.last is odd %}
<td></td>
<td></td>
<td></td>
{% endif %}
{% if (loop.index is even) or loop.last %}
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
I think it's a problem with loop.last but I can't solve this.
Solved by replacing {% if loop.last and loop.last is odd %} by {% if loop.last and passercolles|length is odd %}

cant access to .vars.prototype from macros

I'm trying to custom the add/delete feature of a collection with the data-prototype attr.
To do so, I use some twig macro:
view called by the controller
{# the principal view .html.twig #}
{% from"AppBundle:Macros:tabRangeVal.html.twig" import tableau %}
[...]
{{ tableau('InstrumentSharedUtils/File',form.documentations) }}
{{ tableau('SpecificationsSheet/SpecificationSheet',form.list) }}
[...]
macro for tableau
{# /src/AppBundle/Resources/views/Macros/tabRangeVal.html.twig #}
{% macro tableau(classe, arrayVar) %}
{% from "AppBundle:Form:"~ classe ~ ".html.twig" import val %}
{% from "AppBundle:Form:"~ classe ~ ".html.twig" import label %}
{% from "AppBundle:Macros:dataProto.html.twig" import proDataType %}
<div class="well well-sm">
<h5> {{ form_label(arrayVar) }}</h5>
<table class="table">
<thead>
<tr>
<th><button class="btn btn-default btn-add-row" type="button" id="{{ "add_#{arrayVar.vars.id}" }}"><span class="glyphicon glyphicon-plus"></span></button></th>
{{ label() }}
</tr>
</thead>
<tbody id="{{ "container_#{arrayVar.vars.id}" }}" data-prototype="{{ proDataType(classe, arrayVar.vars.prototype)|e }}">
{% for i in arrayVar %}
<tr >
<td><button class="btn btn-default btn-delete-row"><span class="glyphicon glyphicon-minus"></span></button></td>
{{ val(i) }}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endmacro %}
macro for the data-prototype field
{# /src/AppBundle/Resources/views/Macros/dataProto.html.twig #}
{% macro proDataType(classe, value) %}
{% from "AppBundle:Form:"~ classe ~ ".html.twig" import val %}
<tr>
{% for v in value %}
<td><button class="btn btn-default btn-delete-row"><span class="glyphicon glyphicon-minus"></span></button></td>
{{ val(v) }}
{% endfor %}
</tr>
{% endmacro %}
an exemple of the AppBundle:Form:"~ classe ~ ".html.twig
{# /src/AppBundle/Resources/views/Form/InstrumentSharedUtils/File.html.twig #}
{% macro val(var) %}
<td>{{ form_widget(var.name, { 'attr': { 'class':'form-control' } }) }}</td>
<td>{{ form_widget(var.path, { 'attr': { 'class':'form-control' } }) }}</td>
<td>{{ form_widget(var.isExtra) }}</td>
{% endmacro %}
{% macro label() %}
<th>Name</th>
<th>Path</th>
<th>Is Extra</th>
{% endmacro %}
The problem is that I get the error
Method "name" for object "Symfony\Component\Form\FormView" does not exist in AppBundle:Form:InstrumentSharedUtils/File.html.twig at line 2
The thing that really bothers me is that I can access to the name (and even the others prototype.vars.children) if I dont use macro
by exemple, the following code works:
{# principal view .html.twig #}
{% for i in form.documentations.vars.prototype %}
{{ form_widget(i) }}
{% endfor %}
and i feel like its the exact same as above, with
form.documentations => arrayVar,
arrayVar.vars.prototype => value, and
{% for i in value %}
{{ form_widget(i.name) }}
{{ form_widget(i.path) }}
{{ form_widget(i.isExtra) }}
{% endfor %}
the output should be the same ...
could you help me to find what is wrong in there?
Ok, I will probably flog myself to be so stupid, but by writing it down, I realised (in the last code section) that I made a mistake:
the i in value at the end is already either name or path or isExtra...
so when I try to access to form.documentations.vars.prototype.name.name its logic that I get a beautifull exception...
so the solution was to modify the dataproto macro
{% macro proDataType(classe, value) %}
<tr class='block-to-remove'>
<td><button class='btn btn-default btn-delete-row'><span class='glyphicon glyphicon-minus'></span></button></td>
{% for truc in value %}
<td>{{ form_widget(truc, { 'attr': { 'class':'form-control' } }) }}</td>
{% endfor %}
</tr>
{% endmacro %}
and to send a arrayVar.vars.prototype to it

Resources