count in twig without for loop - symfony

I want to total count resuslt. I have already done it like total group result and In total result in one product....
like:-
Total Group of Product = 15
In one group showing 36 product.
In second group showing 56 product.
I want to show total group product result = 36+56 => 92.
without for loop.
twig file:
<table>
<h2> Showing {{ templates | length }} Products</h2>
{% for groupResults in templates %}
{% if groupResults.doclist.docs[0].first_product_name is defined %}
Show all {{ groupResults | length }} results
<tr>
<td>
{{ groupResults.doclist.docs[0].first_product_name }}
{% if groupResults.doclist.numFound > 4 %}
Show all {{ groupResults.doclist.numFound }} results
{% endif %}
</td>
</tr>
<tr>
{% set count = 0 %}
{% for template in groupResults.doclist.docs %}
<td>
<a href="{{ path("customer_design_editor", { "templateSlug": template.slug, "productSlug": template.product_slug[0] }) }}">
<img src="{{ path("design_template_thumbnail_by_slug", { "slug": template.slug}) }}" alt="" />
</a>
</td>
{% set count = count + 1 %}
{% endfor %}
{% if count < 4 %}
{% for i in count..3 %}
<td> </td>
{% endfor %}
{% endif %}
{% else %}
{% endif %}
{% endfor %}

How about:
{% set totalCount = firstGroup|length + secondGroup|length %}

Related

Dyanamic Variable names in Twig

For a series of similar named string how to I case them to a variable similar to php's $$variable ?
I have tried
{% for col in 1..cols %}
{% set field = 'field'~col %}
<td>
{{ form_widget(form.field) }}
</td>
{% endfor %}
But I get error property does not exist.
Solved it:
{% for col in 1..cols %}
{% set field = 'field'~col %}
<td>
{{ form_widget(attribute(form,field)) }}
</td>
{% endfor %}

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 loop and skip in loop

I pretty new to Twig first of all!
I'm trying to loop through an array of products, like so:
{% for product in products %}
What I further try to do is to check if one of the product.title equals the name lookbook.
if so then this product cannot be showed in my template/page. The things I tried just display an empty div instead of not showing anything.
Is there any way to accomplish this?
What I have so far:
{% for product in products %}
{% if product.title == 'lookbook' %}
.... dont show?? ....
{% else %}
<div class="product>
<h3>{{ product.fulltitle }}</h3>
<a href="{{ product.url | url }}" title="{{ product.fulltitle }}">
<img src="{{ product.image | url_image('220x220x2', product.fulltitle) }}" />
</a>
</div>
{% endif %}
{% endfor %}
I also tried:
{% for product in products and product.title != 'lookbook' %}
Thanks in advance!
Official doc :
{% for user in users if user.active %}
<li>{{ user.username|e }}</li>
{% endfor %}
In your case :
{% for product in products if product.title != 'lookbook' %}
Update 08/2021
Tip
As of Twig 2.10, use the filter filter instead, or an if condition
inside the for body (if your condition depends on a variable updated
inside the loop and you are not using the loop variable).
Try:
{% for product in products %}
{% if product.title != 'lookbook' %}
<div class="product>
<h3>{{ product.fulltitle }}</h3>
<a href="{{ product.url | url }}" title="{{ product.fulltitle }}">
<img src="{{ product.image | url_image('220x220x2', product.fulltitle) }}" />
</a>
</div>
{% endif %}
{% endfor %}

How to make 3 columns table with Twig in Symfony2

I am new to Twig and Symfony2. I was wondering how can I create a 3 column table with Twig. My data comes from a database
So far I've tried everything but still nothin works. I found this on Stackoverflow about making a 2 column table, and it worked perfectly except for me. I want 3 columns .
<table>
{% for var in var1 %}
{% if (loop.index % 2) %}<tr>{% endif %}
<td>
<div class="bloc">
<a href="{{ path('xxxxxxx', {'id':var.id}) }}">
<span>{{ var.name}} </spann></a></div>
<img src="{{ asset(var.image ) }}" />
</div>
</td>
{% if (loop.index % 2) and loop.last %}
<td>&nbsp</td>
{% endif %}
{% if (loop.index0 % 2) or loop.last %}</tr>{% endif %}
{% endfor %}
</table>
ex: var1 contains names and pictures from database.
name1 name2 name3
name4 name5 name6
...
This is what I have ATM
name1 name2
name3 name4 name5
name6 name7 name8
My solution works for any number of columns:
{% set columns = 3 %}
{% for name in names %}
{% if loop.first or loop.index0 is divisibleby(columns) %}
<tr>
{% endif %}
<td>{{ name }}</td>
{% if loop.last and loop.index is not divisibleby(columns) %}
{% for n in range(low=columns - (loop.index % columns), high=1, step=-1) %}
<td> </td>
{% endfor %}
{% endif %}
{% if loop.last or loop.index is divisibleby(columns) %}
</tr>
{% endif %}
{% endfor %}
Correct way are you use batch (array_chunk):
{% for batchResults in result.items|batch(result.total_results / columns) %}
<div class="{{cycle(['left', 'left', 'right'], loop.index)}}">
{% for item in batchResults %}
<div class="{% if loop.last %}last{% endif %}">
{{item}}
</div>
{% endfor %}
</div>
{% endfor %}
Peekmo's solution is correct but there is possibly a neater way using the batch filter in twig. this filter breaks a list into smaller subsets. You control the size and use nested for loops to display rows and their contents. The example in the docs is an exact answer to this problem. The filter will also neatly handle empty cells. Ie you have 8 values in an array and you want a 3 column table, the last cell will be emtpy
http://twig.sensiolabs.org/doc/filters/batch.html
You should try something like that :
<table>
{% for var in var1%}
<tr>
<td>Title1<td>
<td>Title2<td>
<td>Title3<td>
</tr>
<tr>
<td>{{ var.attr1 }}<td>
<td>{{ var.attr2 }}<td>
<td>{{ var.attr3 }}<td>
</tr>
{%endfor%}
</table>
<table>
<tr>
{% for var in var1%}
{% if loop.index0 is divisibleby(3) %}
</tr>
<tr>
{% endif %}
<td>{{ var }}</td>
{% if loop.last %}
</tr>
{% endif %}
{%endfor%}
</table>
I think that could work for your problem, you have to open tag every 3 iterations, and do not forget to close the last one when your loop is terminated.
Untested, but should print a clean table.
<table>
{% for var in var1 %}
{% if not (loop.index0 % 3) %}<tr>{% endif %}
<td>
<div class="bloc">
<a href="{{ path('xxxxxxx', {'id':var.id}) }}">
<span>{{ var.name}} </spann></a></div>
<img src="{{ asset(var.image ) }}" />
</div>
</td>
{% if (loop.index % 2) and loop.last %}
<td>&nbsp</td>
{% endif %}
{% if (loop.index % 3) and loop.last %}
<td>&nbsp</td>
{% endif %}
{% if not (loop.index % 3) or loop.last %}</tr>{% endif %}
{% endfor %}
</table>

symfony2 form error vs field error theme (twig)

In Twig, is there a way to define a different theme for field errors as oppose to form related errors like CSRF error or composite unique constraints?
I want to display the field errors with a <span> and the form errors with a <ul>
{{ form_errors(form) }}
<table>
<tbody>
<tr>
<td>{{ form_label(form.tabla) }}</td>
<td>
{{ form_widget(form.tabla) }}
{{ form_errors(form.tabla) }}
</td>
<td></td>
<td>{{ form_label(form.descripcion) }}</td>
<td>
{{ form_widget(form.descripcion) }}
{{ form_errors(form.descripcion) }}
</td>
<td></td>
</tr>
</tbody>
</table>
This is my form theme that is being used for both cases (not what I want).
{% block field_errors %}
{% if errors|length > 0 %}
<span class="val-error">
{% for error in errors %}
{{ error.messageTemplate|trans(error.messageParameters, 'validators')~'. ' }}
{% endfor %}
</span>
{% endif %}
{% endblock field_errors %}
Is there a way to differentiate both cases?
Form class extends Field. If you set a new theme to field it will be applied to form.
You should override the field_errors block as you did, and then define the form_errors block using another template (with th ul tag).
{% block field_errors %}
{% if errors|length > 0 %}
<span class="val-error">
{% for error in errors %}
{{ error.messageTemplate|trans(error.messageParameters, 'validators')~'. ' }}
{% endfor %}
</span>
{% endif %}
{% endblock field_errors %}
{% block form_errors %}
{% if errors|length > 0 %}
<ul class="val-error">
{% for error in errors %}
<li>{{ error.messageTemplate|trans(error.messageParameters, 'validators')~'. ' }}</li>
{% endfor %}
</ul>
{% endif %}
{% endblock form_errors %}
Since field_* is removed in 2.3 the approved solution will no longer work. A hacky solution I have found is
{% block form_errors %}
{% if errors|length > 0 %}
{% if form.parent is empty %}
<ul class="val-error">
{% for error in errors %}
<li>{{ error.messageTemplate|trans(error.messageParameters, 'validators')~'. ' }}</li>
{% endfor %}
</ul>
{% else %}
<span class="val-error">
{% for error in errors %}
{{ error.messageTemplate|trans(error.messageParameters, 'validators')~'. ' }}
{% endfor %}
</span>
{% endif %}
{% endif %}
{% endblock form_errors %}
So basically what this does is if there is no parent, it knows it is the top level.

Resources