Multidimensional display array values - twig

I have an array:
Array (
[author] => Array (
[0] => john
[1] => smith
)
[description] => Array (
[0] => lorum ipsum
[1] => lorum ipsum
)
)
How to display array in a row containing values author[0] and description[0], author[1] and description[1]
using twig template

Your data are not properly structured. If you really need to iterate over this dataset, you can use something like this one:
{% for key, author in my_array.author %}
{{ author }} {{ my_array.description[key] }}
{% endfor %}

Related

2D Twig Array - printing out the content dynamically

I'm trying to print out a table with keys and values from a 2d-array in twig. The only issue is, that I'm trying to get the values and keys dynamically printed depending on the twig result I get back.
The array I'm getting back from another function can be different with every call, so my goal would be to write a function once instead of multiple times depending on the typ of data I recive.
The array I get is in {{ tableContent }}.
One example of the values are:
{
["Type"] => string(4) "2021"
["Description"] => string(11) "Stundenlohn"
["Symbol"] => string(3) "ABC"
}, {
["Type"] => string(4) "2024"
["Description"] => string(9) "Something"
["Symbol"] => string(3) "XYZ"
}
so in this case I want the table to look something like:
# | Type | Description | Symbol
--+------+-------------+--------
0 | 2021 | Stundenlohn | ABC
1 | 2024 | Something | XYZ
this would work quite well, if I always know the names of the array keys:
{% for key, u in tableContent %}
<li>{{ key }}: {{ u.Type }}</li>
{% endfor %}
And with this I'd get 0: 2021 and 1: 2024
is there a way to not use (in my case) Type but somehow the index?
With this solution I'm working on at the moment I only get the first value:
{% for array in tableContent %}
{% for id, key in array %}
{{id }} | {{key}}<br/>
{% endfor %}<br/>
{% endfor %}

Check in twig if at least on property exists in a given array

Let's assume I have an array $cars where $cars = [$toyota, $vw] and
$toyota= [
'id' => 1,
'color' => 'green',
];
$vw= [
'id' => 7,
'color' => 'red',
];
I wanna do a check in twig to see if at least one of the cars ID exists in a dedicated array ([3, ,7, 15]).
What's the best way to do this? Doing a for loop is not ideal since I cannot do a break if I found the first element matching my criteria. And I also don't wanna print a text twice if both elements satisfy the condition. I just want to print a text if one element does.
I tried doing something weird like
{% if cars in [3, 7, 15] %} .... {% endif %} but if obvously doesn't work since I need to check the id of a car, not the object...
Any suggestions on how to best solve this is much appreciated.
P.S. I know using array_filter in the controller makes it much easier, but sadly that doesn't work for me. That's because I use AJAX and after a submit, I won't have access to cars anymore. Therefore, I need to do it in the view..
You can do something like this (see https://twigfiddle.com/8u3eh5):
{% set found = false %}
{% for car in cars %}
{% if car.id in ids %}
{% set found = true %}
{% endif %}
{% endfor %}
{% if found %}
found
{% else %}
not found
{% endif %}
However, even if this is a working solution, you will be better off by implementing this in PHP code and expose such a function as a Twig test.
Just add a new filter to twig
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('has', function($haystack, $needles) {
if (!is_array($needles)) $needles = [ $needles, ];
return count(array_intersect($haystack, $needles)) > 0;
});
Which you then can use like the following inside twig
{% set data = [ 'foo', 'bar', 'foobar', 'lorem', 'lipsum' ] %}
{% if data | has('foo') %}
data contains foo
{% endif %}
{% if data | has(['lorem', 'lipsum', 'boat']) %}
data contains lorem, lipsum or boat
{% endif %}

Print loop within loop with Twig?

I have nested content in a Twig array. I have months, each of which have days:
In my page.twig:
{% set mock = {
main_title: 'Main title',
months:
[
{
sub_title: 'Title 1',
days: [
{
monday: 'Lorum',
tuesday: 'Ipsum'
}
]
},
{
sub_title: 'Title 2',
days: [
{
monday: 'Dolorem',
tuesday: 'Neque'
}
]
}
]
}
%}
{% include "component.twig" %}
I'm trying to print each month's sub title and the day text under it:
<h2>Title 1</h2>
<h3>Lorum</h3>
<h3>Ipsum</h3>
<h2>Title 2</h2>
<h3>Dolorem</h3>
<h3>Neque</h3>
In component.twig:
{% for m in months %}
<h2>{{ m.sub_title }}</h2>
{% for d in months.days %}
<h3>Print test</h3>
{% endfor %}
{% endfor %}
The month's sub_title in <h2> is printing fine but I can't even get the days in the months to loop correctly.
It appears that the mistake is in your second loop. Instead of months.days, you need to use m.days.
Your first loop pulls the month into the variable m. As your main array months does not have an element days, but each individual month does, your inner loop currently has no content to print.
Just as a side note, I would also recommend adding escaping if this template doesn't use autoescape.
{% for m in months %}
<h2>{{m.sub_title| e}}</h2>
{% for d in m.days %}
<h3>{{ d| e }}</h3>
{% endfor %}
{% endfor %}
------edit-----
I missed on first pass that your sample array has an array "days" with a hash inside it instead of being a single level. In this case, you actually have the equivalent (in PHP anyway of an array in an array) for the days key.
This should do the trick in this case
{% for m in months %}
<h2>{{m.sub_title| e}}</h2>
{% for d in m.days[0] %}
<h3>{{ d| e }}</h3>
{% endfor %}
{% endfor %}

How in twig to set 2 dimentional array in macros

How in twig to set 2 dimentional array in macros and to run it?
I did :
{{ components.menu_item( "Hostels", 'hostel', {'admin/hostel/index': 'All Hostels'}, {'admin/hostel/active_featured_listings': 'Active Featured Hostels'} ) }}
{% macro menu_item(title, active_admin_link, items_array) %}
title::{{ title }}<br>
items_array::{{ dump(items_array) }}<br>
{% endmacro %} {# menu_item END #}
But only 1st array elemented was outputted
array (size=1) 'admin/hostel/index' => string 'All Hostels' (length=11)
What is rigth way and how make for circle?
Thanks!
From the Twig doc:
["foo", "bar"]: Arrays are defined by a sequence of expressions
separated by a comma (,) and wrapped with squared brackets ([]).
So try surround the input with squared brackets, as follow:
{{ components.menu_item( "Hostels", 'hostel', [{'admin/hostel/index': 'All Hostels'}, {'admin/hostel/active_featured_listings': 'Active Featured Hostels'}] ) }}
Hope this help

Counting the number of elements in array

I am looking to count the number of entries I have in an array in Twig. This is the code I've tried:
{%for nc in notcount%}
{{ nc|length }}
{%endfor%}
This however only produces the length of the string of one of the values in the array.
{{nc}} will produce an output of all the values of the array (there are 2) but I want the output to be just the number 2 (the count) and not all the information in the array.
Just use the length filter on the whole array. It works on more than just strings:
{{ notcount|length }}
This expands on the answer by Denis Bubnov.
I used this to find child values of array elements—namely if there was a anchor field in paragraphs on a Drupal 8 site to build a table of contents.
{% set count = 0 %}
{% for anchor in items %}
{% if anchor.content['#paragraph'].field_anchor_link.0.value %}
{% set count = count + 1 %}
{% endif %}
{% endfor %}
{% if count > 0 %}
--- build the toc here --
{% endif %}
Best practice of getting length is use length filter returns the number of items of a sequence or mapping, or the length of a string. For example: {{ notcount | length }}
But you can calculate count of elements in for loop. For example:
{% set count = 0 %}
{% for nc in notcount %}
{% set count = count + 1 %}
{% endfor %}
{{ count }}
This solution helps if you want to calculate count of elements by condition, for example you have a property name inside object and you want to calculate count of objects with not empty names:
{% set countNotEmpty = 0 %}
{% for nc in notcount if nc.name %}
{% set countNotEmpty = countNotEmpty + 1 %}
{% endfor %}
{{ countNotEmpty }}
Useful links:
length
set
for
{%for nc in notcount%}
{{ loop.index }}
{%endfor%}
loop.index -- The current iteration of the loop.
for reference:https://twig.symfony.com/doc/2.x/tags/for.html

Resources