How do I translate this in twig? I have this variable in twig that is an array:
$array = [
['number' => 7, 'name' => 'foo'],
['number' => 8, 'name' => 'bar'],
['number' => 10, 'name' => 'baz'],
// ... and so on and so forth
]
Would like it to be something like this:
The variables are 7 times for foo, 8 times for bar, and 10 times for baz.
Or
The variables are 7 times for foo and 10 times for baz.
Or
The variable is 7 times for foo.
Tried with something like this:
{% set last = array|last %}
{% set array = array|slice(0, array.length - 1) %}
{% trans %}
<p>The variables are
{% for i in array %}
{{ i.number }} times {{ i.name }},
{% endfor %}
, and {{ last.number }} number of {{ last.name }}
.</p>
{% endtrans %}
Thanks!
Try this
The variables are
{% for item in array %}
{% if array|length > 1 and loop.last %}
and
{% endif %}
{{ item.number }} times for {{ item.name }}{% if loop.last %}.{% elseif array|length > 2 %}, {% endif %}
{% endfor %}
Related
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.
I'm struggeling to select a previous for loop in Twig. I'm trying to display a few category titles in a category if that category has subcategories. If the category has no subcategories then it shhould display the titles from the previous loop. Normally this wouldn't be a problem if any category has the same depth. Unfortunatly the categories have different depths.
So what I try to do is create some sort of function that does this for me.
So for example:
Category A -> Category A.sub -> Category A.subsub
Title1 Title1.1 Title1.2
Title1 Title1.1 Title1.2
Category B -> Category B.sub -> Category A.subsub
Title1 Title1.1 Title1.1
Title1 Title1.1 Title1.1
As you can see Category B.sub.sub hasn't any subcategories. If that's the case it should show the subcategories from Category B.sub. Normally I would do something like this:
{% for category in shop.categories %}
{{ category.title }}
{% if category.subs %}
{% for category in category.subs %}
{{ category.title }}
{% if category.subs %}
{% for category in category.subs %}
{{ category.title }}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
Is there any way to create somesort of function that checks if a category has subcategories. If that's not the case the access the previous loop and display those category names.
I thought this was as simple as:
{% elseif not category.subs %}
{# Do this #}
But that's not the case :(
My suggestion is to make the structure of the arrays alike within your php code and don't put such kind of logic in the template.
So in php you wold have something like this:
if (!isset($categoryB['sub']['subsub']) {
$categoryB['sub']['subsub'] = $categoryA['sub']['subsub'];
}
and then your template you just iterate:
{% for category in shop.categories %}
{{ category.title }}
{% for category in category.subs %}
{{ category.title }}
{% for category in category.subs.subsub %}
{{ category.title }}
And I would also suggest to make it recursive so you would have something like:
{% itarerateCategoryes categories %}
Agreeing with Fyntasia I wouldn't have lots of logic in the template, I would parse the data in the controller to the form I wanted.
However assuming your data array is something like (couldn't understand your notation);
$categories = [
0 => [
'top' => ['Atop1', 'Atop2'],
'middle' => ['Amiddle1', 'Amiddle2'],
'bottom' => ['Abottom1', 'Abottom2'],
],
1 => [
'top' => ['Btop1', 'Btop2'],
'middle' => ['Bmiddle1', 'Bmiddle2'],
],
];
Something like;
{% for main_index, category in categories %}
{% if category.top is defined and category.top|length > 0 %}
{{ loop.index0 }} has top values
{% endif %}
{% if category.middle is defined and category.middle|length > 0 %}
{{ loop.index0 }} has middle values
{% endif %}
{% if category.bottom is defined and category.bottom|length > 0 %}
{{ loop.index0 }} has bottom values
{% else %}
{{ loop.index0 }} has no value so using {{ categories[loop.index0 - 1].bottom|join(', ') }}
{% endif %}
<br />
{% endfor %}
Outputs something like;
0 has top values 0 has middle values 0 has bottom values
1 has top values 1 has middle values 1 has no value so using Abottom1, Abottom2
i have a problem with twig syntax and merge function ... I have multiple object with 2 field category and price.
I need to create an array or hash (i guess hash is easier but ... i try both) with sum of prices for each category.
So i try many code, and my last is :
{% set test = [ {'category': 'description', 'price': '1'}, { 'category': 'abc', 'price': '2'}, { 'category':'description', 'price': '3'} ] %}
{% set listCategory={} %}
{% for line in test %}
{% set new_category = { 'category': line.category, 'price': line.price } %}
{% if loop.first %}
{% set listCategory = listCategory|merge([new_category]) %}
{% else %}
{% set flag = false %}
{% for category in listCategory %}
{% if line['category'] == new_category['category'] %}
{% set tmp = line['price'] + new_category['price'] %}
{# i try it too#}
{% set category = category|merge([tmp]) %}
{# or i try this#}
{% set category = category|merge({ (category.price) : category.price + new_category.price }) %}
{{ dump(listCategory) }}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
I try it since 3 hours and i don't know where i make an error.
When i check my array, i test if the key 'name' exist
if yes, i want to add the price of element to the hash price
if no, i want to add a new array in hash with key = 'name'
Anyone have an idea ? thx for your reading.
I think you are looking for something similar to:
{% set test = [ {'category': 'description', 'price': 1}, { 'category': 'abc', 'price': 2}, { 'category':'description', 'price': 3} ] %}
{% set listCategory={} %}
{% for line in test %}
{% set key = line.category %}
{% if listCategory[key] is defined %}
{# notice here that the key is in brackets () because otherwise it will be interpreted as the string "key" %}
{% set listCategory = listCategory|merge({(key):listCategory[line.category]+line.price}) %}
{% else %}
{% set listCategory = listCategory|merge({(key):line.price}) %}
{% endif %}
{{ key }}: {{ listCategory[key] }}
{% endfor %}
How can I echo 1, 2, 3, 4, .... with a twig counter? I can accomplish it with dirty code below but is there a better way?
{% set i = 0 %}
{% for brand in brands %}
{% set i = i + 1 %}
{{ i }}
{% endfor %}
I used {{ cycle(["even", "odd"], loop.index) }} but only getting even or odd.
Also checked Twig docs and range
You can use the loop.index0 or loop.index variable, as mentioned in the docs.
{% for brand in brands %}
{{ loop.index }}
{% endfor %}
Just use {{ loop.index }} or {{ loop.index0 }}if you need it to be 0 indexed
For some reason, a variable I'm setting in one form template bloc is not available in a child form block.
I have an 'entity' field type to present a selection of checkboxes to allow the user to select related items...
$builder
->add( 'title' )
->add(
'apps',
'entity',
[
'class' => 'OurAdminBundle:App',
'choices' => $apps,
'property' => 'title',
'expanded' => true,
'multiple' => true
]
)
And here's the template that renders the form
// Effectively imported using the MopaBootstrapBundle
// {% form_theme form 'OurAdminBundle:Form:fields.html.twig %}
// Further in page theming
{% form_theme form _self %}
// Set variable when on the apps field, so it should be available to all child
// forms
{% block _gallery_apps_widget %}
{% set custom_checkboxes = 1 %}
{{ block('choice_widget') }}
{% endblock %}
// Attempt to retrieve the variable on the checkboxes within the apps entity
/ field
{% block checkbox_widget %}
{{ dump(custom_checkboxes|default(0) }} // Displays 0
{% endblock checkbox_widget %}
Here's the code from the fields.html.twig file (with minor debugging additions...
{% block choice_widget_expanded %}
{{ dump(custom_checkboxes|default(0)) }}
{% set custom_checkboxes = custom_checkboxes|default(0) %}
{{ dump(custom_checkboxes|default(0)) }}
{% spaceless %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default(''))}) %}
{% set label_attr = label_attr|merge({'class': (label_attr.class ~ ' ' ~ (widget_type != '' ? (multiple ? 'checkbox' : 'radio') ~ '-' ~ widget_type : ''))}) %}
{% if expanded %}
{% set attr = attr|merge({'class': attr.class|default(horizontal_input_wrapper_class)}) %}
{% endif %}
{% for child in form %}
{% if widget_type != 'inline' %}
<div class="{{ multiple ? 'checkbox' : 'radio' }}">
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ form_widget(child, {'horizontal_label_class': horizontal_label_class, 'horizontal_input_wrapper_class': horizontal_input_wrapper_class, 'attr': {'class': attr.widget_class|default('')}}) }}
{{ child.vars.label|trans({}, translation_domain) }}
</label>
{% if widget_type != 'inline' %}
</div>
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock choice_widget_expanded %}
... which successfully displays '1' on both counts.
I've racked my brains over this one, but can't for the life of me understand why I can't access the variable in the checkbox_widget block. Please help.
This is due to how Symfony renders form fields when calling form_widget() or any other form* family of functions.
Symfony creates a new separate scope which do not share the scope of the parent (in order to prevent scope polluting while rendering fields).
If you which to pass a variable to the checkbox widget, edit the form_widget call in the choice_widget_expanded to pass on the custom_checkboxes as so (added tabbing for clarity only):
{{ form_widget(child, {
'horizontal_label_class': horizontal_label_class,
'horizontal_input_wrapper_class': horizontal_input_wrapper_class,
'attr': {'class': attr.widget_class|default('')},
'custom_checkboxes': custom_checkboxes
}) }}