How to get an item of array by a field value? - symfony

I have an object called "template.Highlights" where exists 7 items. All items have 2 fields: 'name','desc'. How can I access (without multiples if's) an item through the value of the 'name' field? (the names are: 'hl1', 'hl2', 'hl3', 'hl4', 'hl5', 'hl6', 'hl7').

{% for template.Highlights as highlight %}
{% if highlight.name == 'hl5' %}
{% set item = highlight %}
{% endif %}
{% endfor %}
{{ item.name }}, {{ item.desc }}

Related

Symfony 5+ nested form collection rendering

{% form_theme form _self %}
{% block collection_entry_row %}
{% set fields = form.attributes.children[0].children %}
{% for key, field in fields %}
{{ form_widget(field) }}
{{ form_widget(fields[key]) }}
{% endfor %}
{% endblock %}
And I get this error:
Neither the property "attributes" nor one of the methods "attributes()", "getattributes()"/"isattributes()"/"hasattributes()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".
But this
{% set fields = form.attributes.children[0] %}
{% for key, field in fields %}
{{ dump(field) }}
{% endfor %}
Produces this:
Symfony\Component\Form\FormView {#2150 ▼
+vars: array:33 [▶]
+parent: Symfony\Component\Form\FormView {#2203 ▶}
+children: []
-rendered: false
-methodRendered: false
}
And yet inside the form_start() I can do the following and render one field at a time:
{% set tempInput = form.children['attributes'].children[0].children['attributes'].children[0].children['pin'] %}
{{ form_widget(tempInput) }}
Thoughts?
just had the same questions as you about this subject, and since i didn't understands the way to use the "{% block collection_row %}" i've found this following workaround.
I find out that the problem i had was coming from the 2 last item of the form.children: "submit" and "_token".
Because, of course, they will not have the variable name you are searching in the other "real" forms childs.
So i just added a check to the length of the children array to exclude this "submit" and "_token" items.
(The test might certainly be different for your case).
{% for child in form.children %}
{% if not child.children | length != 4 %} // my array has 4 items, submit and _token have none
{{ form_widget(child.children.variableName) }}
{% endif %}
{% endfor %}
As you can see you can access your collection variable between the if like this:
{{ form_widget(child.children.variableName) }}
Peace.

Group inside Repeater ACF Pro WordPress Timber

I have checked the documentation and various posts and could not find examples of this.
What I want is to access a field of a group, which is within a repeater in ACF Pro, using Timber/Twig.
What I have is:
{% for item in post.meta('main_field') %}
{{ item.normal_field }} // outputs fine
{% for group_name in item.main_field %}
{{ group_name.group_field }} // outputs nothing
{% endfor %}
{% for group_name in item %}
{{ group_name.group_field }} // outputs only the first instance
{% endfor %}
{% endfor %}
If I put {{ item.group_name.group_field }} I get only the data from the first item output.
I have also tried adding {% set group = post.meta('group_name') %} both before and after {% for item in post.meta('main_field') %} which outputs nothing, when referenced by {{ group.group_field }}.
So how do you reference a group within a repeater?

Using a counter in a Twig node template

Setting up a Drupal 8 custom view for Top 4 items, I want a different layout for item 1 than the remaining. I have override files for the custom view, but for this example I'm using base files to keep it simple.
In views-view.html.twig base file we have:
<div class="view-content">
{{ rows }}
</div>
In node.html.twig base file we have:
<div {{ content_attributes.addClass('content') }}>
{{ content }}
</div>
In node.html.twig I am aiming for something like:
{% if row_counter = 1 %}
output this markup / fields
{% else %}
do something boring with the other 3 items.
{% endif %}
I was able to set row_counter in the views-view.twig.html file:
{% for row in rows %}
{% set row_counter = loop.index %}
<div{{ row.attributes }}>
{{ row_counter }}
</div>
{% endfor %}
But I need to check against the value of {{ row_counter }} in the node.html.twig file....
What other properties are available in node.html.twig to check against its position in the list?
From the documentation
The loop variable
Inside of a for loop block you can access some special variables:
Variable Description
-----------------------------------------------------------------
loop.index The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex The number of iterations from the end of the loop (1 indexed)
loop.revindex0 The number of iterations from the end of the loop (0 indexed)
loop.first True if first iteration
loop.last True if last iteration
loop.length The number of items in the sequence
loop.parent The parent context
edit: every variable know in the parent template is also known inside an include as context is passed by default. Only macro's don't know the parent's context
controller
<?php
require __DIR__ . '/../requires/propel_standalone.php';
echo $twig->render('tests/items.html', [
'items' => [
'Abc',
'def',
'ghi',
'jkl',
'mno',
'pqr',
'stu',
'vwx',
'z',
],
]);
items.twig
<!doctype>
<html>
<head><title>Test</title></head>
<body>
{% for item in items %}
{% include "tests/item.html" %}
{% endfor %}
</body>
</html>
item.twig
{% set order = 'Nothing to report' %}
{% if loop.first %}
{% set order = 'I\'m first' %}
{% endif %}
{% if loop.last %}
{% set order = 'I\'m last' %}
{% endif %}
{% if loop.index is even %}
{% set order = 'I\'m even' %}
{% endif %}
{% if loop.index is divisible by(5) %}
{% set order = 'I can be dived by 5' %}
{% endif %}
{% if loop.index is divisible by(3) %}
{% set order = 'I can be dived by 3' %}
{% endif %}
<div>
<b>{{ loop.index }}:</b>{{ order }} - {{ item }}
</div>
You could do something like this if a class is enough:
Your views template:
{% for row in rows %}
<div class="{% if loop.index == 1 %}first_element{% endif %}">
{{ row.content }}
</div>
{% endfor %}
And then just style it appropriately.

Twig compare two values in different arrays

First of all I'm learning Twig.
I was wondering if it is possible wit Twig to compare two different values from different arrays/lists?!
I have two list of items I call them like so:
{% if page.cart %}
{% for product in page.cart.products %}
{{ product.id }}
{% endfor %}
{% endif %}
And:
{% if products %}
{% for product in products %}
{{ product.id }}
{% endfor %}
{% endif %}
I want to compare both product.id's so I can create a new statement. Is there any way to compare both values? The idea is to check if an id is present in page.cart.products and if so then do something.
I want to create a new statement to display some info. Something like so:
{% if page.cart %}
{% for product in page.cart.products %}
{% set cartId %}{{ product.id }}{% endset %}
{% endfor %}
{% endif %}
{% if products %}
{% for product in products %}
{% set listId %}{{ product.id }}{% endset %}
{% endfor %}
{% endif %}
{% if cartId == listId %}
.... do this ....
{% endif %}
Any help greatly appreciated!
You can loop over one array and check if the id is present in the second one. If it's there, you can do something.
{# In case you want to store them, you can do so in an array #}
{% set repeatedIds = [] %}
{% for productCart in page.cart.products if page.cart %}
{% for product in products if products %}
{% if productCart.id == product.id %}
<p>This id -> {{ product.id }} is already in page.cart.products</p>
{% set repeatedIds = repeatedIds|merge([product.id]) %}
{% endif %}
{% endfor %}
{% endfor %}
{{ dump(repeatedIds) }}
It's a very basic search algorithm and the cost is quadratic. Obviously, there are more efficient ways to look for an element in an array (though more complicated to implement).
If the amount of products you have to deal with is not very big, you could use this solution. However, if you have, let's say, more than one hundred products in each array (or you feel that the algorithm is slowing down your loading time), you could do this process in the controller using more sophisticated methods and PHP and just pass the result to the template.
Hope it helps.

How to retrieve the value (string) of an array's element and use it to retrieve the property value of an entity?

how to retrieve the value (string) of an array's element and retrieve the property value of an entity? I tried this:
{% for item in items %} //item is an entity
{% for column in columns %} //column is just an array with name of columns
{% set columna = column.value %}
{{ item.columna }}
{% endfor %}
{% endfor %}
If you want to access dynamically a property of an object, you can use the attribute function :
{% for item in items %}
{% for column in columns %}
{{ attribute(item , column.value) }}
{% endfor %}
{% endfor %}
Try this:
{% for item in items %} //item is an entity
{% for column in columns %} //column is just an array with name of columns
{% set columna = column.value %}
{{ attribute(item, columna) }}
{% endfor %}
{% endfor %}
I recommend reading the documentation.

Resources