How Would You Make A Two Column Table With Twig? - php

I can't for the life of me figure out how to add a </tr><tr> every OTHER iteration in a Twig loop.
For instance:
$numArray = array(12,13,14,15,16,17,18);
Passed to twig, I would loop a table like:
<table>
{% for num in numArray %}
<tr>
<td>
{{num}}
</td>
</tr>
{% endfor %}
</table>
This would output:
+-----------+
| 12 |
+-----------+
| 13 |
+-----------+
| 14 |
+-----------+
| 15 |
+-----------+
| 16 |
+-----------+
| 17 |
+-----------+
| 18 |
+-----------+
What I'd like to do is get something like this:
+-----------+-----------+
| 12 | 13 |
+-----------+-----------+
| 14 | 15 |
+-----------+-----------+
| 16 | 17 |
+-----------+-----------+
| 18 | |
+-----------+-----------+
But I can't for the life of me figure out a way to alternate my row input with anything that doesn't seem hacky. Honestly I can't even get hacky to work. Is there a method for this? Or, should I be looking to write my own extension?

The proper way of doing this is using the batch filter. It is new in 1.12.3.
<table>
{% for row in numArray|batch(2) %}
<tr>
{% for column in row %}
<td>{{ column }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Ref: http://twig.sensiolabs.org/doc/filters/batch.html

Something like this would work:
<table>
<tr>
{% for num in numArray %}
<td>
{{num}}
</td>
{% if loop.index is even %}
</tr>
<tr>
{% endif %}
{% endfor %}
{% if num|length is odd %}
<td></td>
{% endif %}
</tr>
</table>
An alternative way, that feels much less hacky:
<table>
{% for i in range(0, numArray|length-1, 2) %}
<tr>
<td>{{ numArray[i] }}</td>
<td>{{ numArray[i+1]|default("") }}</td>
</tr>
{% endfor %}
</table>

For this specific case you can prepare your array before. So in a loop you will have in each row two variables. Try first example from this site http://twig.sensiolabs.org/doc/templates.html

Related

Twig dividing data into tables

I am working on a webapplication but ive ran into a hiccup, I have gathered data from my database and displayed the records into a datatable, my problem is that I can not just have one table the client wants me to divide the table into multiple based on what interger is in a column(omloopNummer).
The best ive gotten so far is with the following code it wil split the table up into lets say 4 tables if the interger in the database wil go 1,2,3,4 but it wil only show 1 record in each table while it should be more.
If there is any other simple solution to this instead of using twig I would be happy to try it.
<div id="index" class="table-responsive">
{% set i = 1 %}
{% for duel in duels %}
{% if duel.omloopNummer == i %}
{% set i = i + 1 %}
<table id="" class="table display-" style="width: 90%; margin-top: 30px">
<thead>
<tr>
<th>Omloop</th>
<th>Team 1</th>
<th>vs</th>
<th>Team 2</th>
<th>Acties</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ duel.omloopNummer }}</td>
<td>{{ duel.team1 }}</td>
<td>vs</td>
<td>{{ duel.team2 }}</td>
<td>{{ include('duel/_delete_form.html.twig') }}</td>
</tr>
</tbody>
</table>
{% endif %}
{% endfor %}
You could use PHP to group Duels by omloopNummer in the controller before passing to twig.
$duels = $duelRepository->findAll();
$sorted = [];
foreach($duels as $duel){
$sorted[$duel->getOmloopNummer()][] = $duel;
}
return $this->render('template.html.twig', [
'duel_groups' => $sorted,
]);
Then in twig, loop through the sorted array building a table for each non-empty group and inside each tbody loop through the group.
{% for group in duel_groups %}
...
{% if group is not empty %}
<table>
...
<tbody>
{% for duel in group %}
<tr>...</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
...
{% endfor %}

Convert Key Value to matrix in twig

I using twig to render data, to html. Data I got from server is a key-value. for example :
| Key | Value |
|-----|-------|
| A | 1 |
| A | 2 |
| B | |
| C | 10 |
I need to render this data to table like this :
| A | B | C |
|---|---|----|
| 1 | 0 | 10 |
| 2 | 0 | 0 |
this is what i've tried :
<table>
<thead>
<tr>
{% set now = '' %}
{% set arrKey = [] %}
{% for data in datas %}
{% if now != data.key %}
<th>{{ data.key }}</th>
{% set now = data.key %}
{% else %}
{% set arrKey = arrKey|merge([now]) %}
{% endif %}
{% endfor %}
</tr>
</thead>
<tbody>
{% set rowNow = '' %}
{% for key in arrKey %}
<tr>
{% for data in datas %}
{% if rowNow != dataKey %}
{% if data.value is empty %}
<td>0</td>
{% else %}
<td>{{ data.value }}</td>
{% endif %}
{% set rowNow = data.key %}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
but this still wrong, it will render :
| A | B | C |
|---|---|----|
| 1 | 0 | 10 |
| 1 | 0 | 10 |
please help me how to solve this?
The best way to manage this is to convert the data inside the controller. This is because the merge filter is a pain to work with. Anyway if you wanted to do it in pure twig, here is how
{% set data = [
{ 'key': 'A', 'value': 1, },
{ 'key': 'A', 'value': 2, },
{ 'key': 'B', 'value': null, },
{ 'key': 'C', 'value': 2, },
{ 'key': 'C', 'value': 4, },
{ 'key': 'A', 'value': 3, },
{ 'key': 'A', 'value': 4, },
] %}
{% set temp = [] %}
{% for row in data %}
{% if not (row.key in temp|keys) %}
{% set temp = temp | merge({ (row.key) : [] }) %}
{% endif %}
{% set temp = temp | merge({(row.key):(temp[row.key]|merge([ row.value, ]))}) %}
{% endfor %}
{% set max = 0 %}
{% for data in temp %}{% if data|length > max %}{% set max = data|length %}{% endif %}{% endfor %}
<table>
<tr>
{% for key in temp|keys %}
<th>{{ key }}</th>
{% endfor %}
</tr>
{% for i in 0..(max-1) %}
<tr>
{% for data in temp %}
<td>{{ data[i] | default(0) }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
demo

How to say "if this translation is empty"

I want to have this image not showing if the translation is empty or non existing
<img class="partners-logo" src="{{ 'page.image.path' | trans | raw }}">
So can I wrap a logic loop around it as in the following code?
{% if {{ 'page.image.path' | trans }} is not null %}
<img class="partners-logo" src="{{ 'page.image.path' | trans | raw }}">
{% endif %}
Obviously not right? Then how should it be?
You can do something like that :
{% if "page.image.path"|trans != "page.image.path" %}
This will check if the result of the translation is different from the translation key : if a translation key has no translation, filter trans returns the translation key.

increase size of excerpt in shopify

i am displaying blog articles in some text and at the end Read more button in order to view complete article in my shopify web
this is the code that i am using
<div class="rte">
{% if article.image %}
{% assign image_alt = article.title | escape %}
<p>{{ article | img_url: '1024x1024' | img_tag: image_alt, 'article__image' | link_to: article.url }}</p>
{% endif %}
{% if article.excerpt.size > 0 %}
{{ article.excerpt }}
{% else %}
<p>{{ article.content | strip_html | truncatewords: 100 }}</p>
{% endif %}
</div>
it worked very well now i set only one article to display
{% paginate blog.articles by 1 %}
it displayed only one article.
i just want to increase the short description text of article to 50% with read more button.
is this possible to increase the size of article.excerpt so that i will display more text with read more button
i tried this but this is not work for me
{{ article.excerpt.size = 1200 }}

Twig representation of array

How can I represent array data given in the following format:
array(3) {
[0]=> array(4) {["cohort"]=5 ["total"]=5 ["week"]=1 ["active"]=2 }
[1]=> array(4) {["cohort"]=5 ["total"]=5 ["week"]=2 ["active"]=1 }
[2]=> array(4) {["cohort"]=6 ["total"]=3 ["week"]=1 ["active"]=1 }
}
To be shown in twig like this:
cohort| total| 1 (week) | 2 (week)
------------------------------------
5 | 5 | 2 | 1
6 | 3 | 1 | -
My problem, is that I don't know how to loop through the array, so that I only get row numbers equal to unique cohort number (only 5 and 6, not 5,5,6), get 'week' number as column name and 'active' value to be shown in relevant 'week' column and relevant cohort row
I tried to do this:
<table>
<tr><td>Cohort</td><td>Registered users</td>
{% for week in logged_users %}
{% if week.week_number not in weekArray %}
<td>{{week.week_number}}</td>
{% set weekArray = weekArray|merge([week.week_number]) %}
{% endif %}
{% endfor %}
</tr>
{% for data in logged_users %}
<tr>
{% if data.cohort not in cohortArray %}
<td>{{data.cohort}}</td>
<td>{{ data.total_users }}</td>
{% for active in logged_users %}
<td>{{ active.active_users }}</td>
{% endfor %}
{% set cohortArray = cohortArray|merge([data.cohort]) %}
{% endif %}
</tr>
{% endfor %}
</table>
but in the result I get this:
<table>
<thead>
<tr><th>cohort</th><th>total</th><th>1 - week</th><th>2 - week</th></tr>
</thead>
<tbody>
{% for i,a in data %}
<tr>
<td>{{ a.cohort }}</td><td>{{ a.total }}</td><td>{{ (a.week==1 ? a.active : '-') }}</td><td>{{ (a.week==2 ? a.active : '-') }</td>
</tr>
{% endfor %}
</tbody>
</table>

Categories