Increment declared integer variable - twig

I try to do zebra striping:
{% set counter = 0 %}
{% for entity in entities %}
<tr class="{{ cycle(['odd', 'even'], counter) }}">
{% counter++ %}
but I am getting error:
Unexpected tag name "counter" (expecting closing tag for the "for" tag
defined near line 11)
Could somebody give me solution?
[EDIT]
My bad solution is so easy:
{% set counter = counter + 1 %}

There's an easier way to do what you want:
{{ cycle(["even", "odd"], loop.index) }}
See the docs for the loop goodies.

If you want to have full control over the html, you can try this:
{% if loop.index is divisibleby(2) %}
...
{% endif %}
You can read it here: http://twig.sensiolabs.org/doc/tests/divisibleby.html
note that loop.index is used 'as-is', it does not refer to a variable rather the hidden indexing of the for loop.

Related

TWIG / GravCMS: Use loop-variable of for-loop inside modular template

Here is my current code:
{% for module in page.collection() %}
{% set index = loop.index %}
{{ module.content|raw }}
{% endfor %}
I'd like to access index inside the module.html.twig, or even better, the entire loop variable.
How do I do that?
I found it myself:
{% for module in page.collection() if not module.header.visible is same as(false) %}
{% include module.template ~ '.html.twig' with {'page':module, 'loop':loop} %}
{% endfor %}
This loop willautomatically grab the template which is linked to the modular page and pass the required variables down. Also, the loop will only include modular subpages which are not hidden. Great, isn't it?

How to use Twig_Markup object type in an If statement

I want to reuse pretty heavy logic only code a few times, in php I would use a function, but in twig I went with a solution from this old question.
In short, I use a macro like that:
{% import _self as test %}
{% macro check() %}
{{ test }}
{% endmacro %}
{% set v = test.check() %}
{% if v == 'test' %}
this should display
{% endif %}
Here is a fiddle: https://twigfiddle.com/kyv3zr/2
The problem is that v is a Twig_markup object. It doesn't seem to have any public properties. Running dump on it gives me this:
object(Twig_Markup)#1244 (2) { ["content":protected]=> string(13) " 1 " ["charset":protected]=> string(5) "UTF-8" }
How do I use it in an if statement?
Or is there a better way of storing a logic only code for reuse across templates?
If the object is called v then the dump seems to show it has a content value, so try:
{% if v.content == '1' %}
{# do something here #}
{% endif %}
not certain though, but try it.
EDIT #2 - based on comments question.
So I guess if you want to use v in an if statement, you would use it like so:
{% if v == '1' %}
{# do something here #}
{% endif %}
This presumes it does equal to "1".

for loop counter with Twig or Swig

Anyone know of a clean way to do this in Twig/Swig:
{% for(i = 0; i < 100; i++) %}
blah....
{% endfor %}
If you have a number, then you can just convert this to an array and then use Swig's standard for tag. This is simplest if you always want to 'start' the loop from 0 though.
For example:
{% set productCount = 6 %}
{% set productCountAsArray = Array(productCount) %}
{# This will run productCount times #}
{% for x, y in productCountAsArray %}
This is for number: {{ x }}
{% endfor %}
The swig docs have since (ivoba's answer) been updated and now contain special loop variables, which include loop.index:
{% for x in y %}
{% if loop.first %}<ul>{% endif %}
<li>{{ loop.index }} - {{ loop.key }}: {{ x }}</li>
{% if loop.last %}</ul>{% endif %}
{% endfor %}
http://paularmstrong.github.io/swig/docs/#tags-for
For twig its:
{% for i in 0..100 %}
* {{ i }}
{% endfor %}
From http://twig.sensiolabs.org/doc/tags/for.html
For swig the docs dont mention it yet:
https://github.com/paularmstrong/swig/blob/master/docs/tags.md#for
i cant really tell but it might be not supported in swig since its django inspired and django also seems to lack this feature nativly: https://code.djangoproject.com/ticket/5172
so i would like to pass the swig part to the next one.

How do you translate array items and join them?

Using twig, how can I translate all items in an array and join them with a slash?
Do I have to use an additional variable or is there a cleverer method?
For the moment, I'm doing something like this:
{% set labels = [] %}
{% for feature in menu_item.features %}
{% set labels = labels|merge([feature|trans([], 'features')]) %}
{% endfor %}
{{ labels | join(' / ')}}
It sucks.
Why not just output the content while you're looping ?
{% for feature in menu_item.features %}
{% if loop.index0 > 0 %}/{% endif %}
{{feature|trans}}
{% endfor %}
Maybe I'm late to the party, but you can now do this easily with the map filter:
{{ menu_item.features|map(feature => feature|trans)|join(' / ') }}
See documentation:
Twig >v1.41: https://twig.symfony.com/doc/1.x/filters/map.html
Twig >v2.10: https://twig.symfony.com/doc/2.x/filters/map.html
Twig v3.x: https://twig.symfony.com/doc/3.x/filters/map.html
Not everything should be done within the "view".
This type of code is probably much better placed within your controller logic and then passed into the view as the merged+joined result. Because in your example all you're doing is compiling a result which can much more easily be done within code.

Twig: in_array or similar possible within if statement?

I am using Twig as templating engine and I am really loving it. However, now I have run in a situation which definitely mustbe accomplishable in a simpler way than I have found.
What I have right now is this:
{% for myVar in someArray %}
{% set found = 0 %}
{% for id, data in someOtherArray %}
{% if id == myVar %}
{{ myVar }} exists within someOtherArray.
{% set found = 1 %}
{% endif %}
{% endfor %}
{% if found == 0 %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
What I am looking for is something more like this:
{% for myVar in someArray %}
{% if myVar is in_array(array_keys(someOtherArray)) %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
Is there a way to accomplish this which I haven't seen yet?
If I need to create my own extension, how can I access myVar within the test function?
Thanks for your help!
You just have to change the second line of your second code-block from
{% if myVar is in_array(array_keys(someOtherArray)) %}
to
{% if myVar in someOtherArray|keys %}
in is the containment-operator and keys a filter that returns an arrays keys.
Just to clear some things up here. The answer that was accepted does not do the same as PHP in_array.
To do the same as PHP in_array use following expression:
{% if myVar in myArray %}
If you want to negate this you should use this:
{% if myVar not in myArray %}
Try this
{% if var in ['foo', 'bar', 'beer'] %}
...
{% endif %}
another example following #jake stayman:
{% for key, item in row.divs %}
{% if (key not in [1,2,9]) %} // eliminate element 1,2,9
<li>{{ item }}</li>
{% endif %}
{% endfor %}
Though The above answers are right, I found something more user-friendly approach while using ternary operator.
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
If someone need to work through foreach then,
{% for attachment in attachments %}
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
{% endfor %}
It should help you.
{% for user in users if user.active and user.id not 1 %}
{{ user.name }}
{% endfor %}
More info: http://twig.sensiolabs.org/doc/tags/for.html
Here's one to complete the answers with all the possibilities of Twig these days:
To achieve something like this:
{% for myVar in someArray %}
{% if myVar in someOtherArray|keys %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
(https://twigfiddle.com/0b5crp)
You could also use array mapping and have the following one-liner:
(Twig >= 1.41 or >= 2.10 or any 3.x version)
{{ someArray|map(myVar => myVar ~ (myVar not in someOtherArray|keys ? ' doesn\'t') ~ ' exists within someOtherArray.')|join('\n') }}
Which outputs something quite similar.
Also see this Twig fiddle: https://twigfiddle.com/dlxj9g
{% if myVar in myArray %} without keys helps me

Resources