for loop counter with Twig or Swig - node.js

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.

Related

How to render HTML to a variable

I need to render a list of HTML elements with content and put it into a variable. How can I do this efficient in twig?
e.g. I need to render the post tracking URLs from an order which can have several shippings / parcels.
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
Instead of printing this directly into the output I like first to put this rendered output into a variable like
{% set output = ... %}
...
{{ output }}
How can I do this in twig?
Just the concatenate the html to the output variable. Keep in mind you'll need to define to the variable outside the for-loop in order to use it outside the loop.
{% set foo = '' %}
{% for i in 1..10 %}
{% set foo = foo ~ ''~i~'' %}
{% endfor %}
{{ foo|raw }}
demo
After long search I found a better more efficient way
you can use {% set var %} with {% endset %} as a whole output block. Means the whole output will be set to the variable. This makes the life much easier and readable.
e.g.
{% set trackingText %}
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
{% endset %}
...
{% if trackingText|trim is not empty %}
You can track the delivery by using the following URL:<br/>
{{ trackingText }}
<br/>
{% endif %}

Variable/Index within head of a loop

I have a for-loop within another for-loop and I would like the inner for-loop to go through the array test[INDEX] with [INDEX] being the index of the outer for-loop. I know I can get the loops index with the variable {{ loop.index() }}, however I do not know how to apply that within the head of my inner loop.
I've tried {% for x in test.{{ loop.index0 }} %}, but that throws me the error
Expected name or number.
Is there any way to do this?
In twig you can also use the array notation to get values from a variable
A note here is that the default loop.index is 1 indexed so you might want to use loop.index0 to get the correct offset
{% for f in foo %}
- {{ f }}: {{ bar[loop.index0] }}
{% endfor %}
As an alternative you can also get the key in the {% for key, value ... format
{% for key, value in foo %}
- {{ value }}: {{ bar[key] }}
{% endfor %}
demo
edit
As for you comment, you can succesfuly use this in any inner-loop, here is a more readable example
{% for country in countries %}
{{ country }}:
{% if cities[loop.index0]|default %}
<ul>
{% for city in cities[loop.index0] %}
<li>{{ city }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
demo

Scope of variable in jinja2 template

I am writing jinja2 template based application. I am trying to write a logic to set variable.
{% set last_item = none %}
{% for u in users %}
{% if not u.username == user.username%}
{% if g.user.is_bestfriend(u) %}
{% set last_item = 'true' %}
{% endif %}
{% endif %}
{% endfor %}
{{last_item}}
but after {% endfor %}, last_item value is again set to none, instead of true. Is there any way to set it to true in jinja2 template?
Since version 2.10 you can do this using a namespace variable, set before entering the scope:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
See also the documentation: http://jinja.pocoo.org/docs/2.10/templates/#assignments
Due to scoping rules in jinja2, you cannot access a variable outside the scope that it was set in. Sorry :(

Testing current value of cycle

I want to render blocks of HTML in alternate orientations. Is this the correct syntax in order to get the current value of cycle?
{% if ( {{ cycle(['odd', 'even']) }} == 'odd' ) %}
foo
{% elseif %}
bar
{% endif %}
cycle(['odd', 'even']) should not be inside {{ }} in the if
statement
cycle() should have a second parameter given that counts the amount of loops
the {% elseif %} should either have a condition or be changed to {% else %}
This is what you should do to get the code to work as you want it to (loop 10 times):
{% for i in 0..9 %}
{% if cycle(['odd', 'even'], i) == 'odd' %}
foo
{% else %}
bar
{% endif %}
{% endfor %}
If you want the for to loop objects you can use loop.index (starts at 1) instead of i:
{% for object in objects %}
{% if cycle(['even', 'odd'], loop.index) == 'odd' %}
foo
{% else %}
bar
{% endif %}
{% endfor %}
or loop.index0 (starts at 0):
{% for object in objects %}
{% if cycle(['odd', 'even'], loop.index0) == 'odd' %}
foo
{% else %}
bar
{% endif %}
{% endfor %}

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