Twig loop.first not working - twig

I have the following :
{% for field in fields -%}
<div class="item{% if loop.first %} active{% endif %}">
{{ field.content }}
</div>
{%- endfor %}
but it's adding the active class to every field wrapper, rather than just the first which is my intention.

Thanks Darkbee. User malfunction here. The code was in a nested template file ( Drupal ) and the loop I thought I was iterating through was actually in a higher level template file.

Related

A For Loop in Jinja can't be used again or how to move First

When reusing the same SQLAlchemy Result to iterate it only works the first time.
See the below how I get all the qual.workforce but none of the displayname, busunit or certcount's:
<ul class="empltype">
{% for qual in allquals %}
<li>{{qual.workforce}}</li>
{% endfor %}
</ul>
<ul class="names">
{% for qual in allquals %}
<li>{{qual.displayname}}</li>
{% endfor %}
</ul>
<ul class="busunit">
{% for qual in allquals %}
<li>{{qual.busunit}}</li>
{% endfor %}
</ul>
<ul class="certcount">
{% for qual in allquals %}
<li>{{qual.certcount}}</li>
{% endfor %}
I would like to MoveFirst before the 3 loops for displaynames, busunit and certcount so they all work.
I don't want have 4 copies of the same variable (allquals1,2,3) even though I know that will work. I'm guessing the jinja render engine only iterates through objects once, is there a way to tell it to iterate over the same result set each time its used in a loop?
it happens just because the result is a generator, and it's values can be accessed only once. you have to do allquals = list(query_result) to iterate multiple times over it

Just a regular block reuse with Twig - how to?

Imagine we have a block template which we want to use many times on a page. And every time we need to do three things:
set a class on the top level
set a title
add some content
How to achieve this on Twig?
I know about macro, but it doesn't take content.
I know about block, but it doesn't take parameters.
So... how to do this in a normal way?
Since I don't know how, I'll use an imaginary constructs 'blockdef' and 'blockuse' later on to demonstrate the task (which is absolutely ordinary).
So let's say we have this cute Twig block template:
blocks.twig:
{% blockdef myblock(class, title) %}
<div class="block {{class}}">
<div class="inner">
<div class="title">{{title}}</div>
<div class="content">{{content}}</div>
</div>
</div>
{% endgoodblock %}
And want to use it like this:
main.twig:
{% blockuse myblock('c1', 'Title1' %}
<p>Block 1 content</p>
{% endblockuse %}
{% blockuse myblock('c2', 'Title2' %}
<p>Block 2 content</p>
{% endblockuse %}
{% blockuse myblock('c3', 'Title3' %}
<p>Block 3 content</p>
{% endblockuse %}
Is there anything like this?
UPDATE. For example, this is how it's solved on Jade:
mixin myblock(cls, title)
.block(class=cls)
.inner
.title= title
.content
block
+myblock('c1', 'Title1')
p Block 1 content
+myblock('c2', 'Title2')
p Block 2 content
+myblock('c3', 'Title3')
p Block 3 content
You could use include with:
{% include 'template.html' with {'class': 'class', 'title': 'title', 'content: 'content'} %}

How to do a foreach loop in a Twig

Here i have attached screenshot,in that 2nd section 2 rows are present. i need to display only one row with custom code condition, If i disable from admin side,it will work correctly,but i need loop condition for enable and disable to display only row. Here is my code,
<div class="col-md-12" >{% for module in modules %}<div class="img-responsive">
{{ module }}
{% endfor %}</div></div>
</div>
There's special loop variables inside a loop that let's you keep track of index and more. In your case loop.index.
<div class="col-md-12" >
{% for module in modules %}
<div class="img-responsive">
{# Replace 1 with a specific index you want to use as condition #}
{% if loop.index == 1 %}
{{ module }}
{% else %}
No module
{% endif %}
</div>
{% endfor %}
</div>

How to filter image list with twig in grav

I am inserting a list of sponsor images in a sidebar in grav and want to show only images starting with sponsor_.
At the moment, my code adds any image in the page folder.
base.html.twig:
<div class="sidebar-right-content">
<!-- insert R sidebar images here -->
<div class="sponsor-image">
<h3>Sponsors</h3>
{% for image in page.media.images %}
<br>{{ image.html }}
{% endfor %}
</div>
I have tried restricting the images returned by using the expression below, but no images are returned:
{% for image in page.media.images if image matches '/^sponsor.*$/' %}
Is there a way to use a filter in this context?
try: {% image in page.media.images |contains('sponsor') %}
After some testing of a few options, I found a somewhat inelegant way to solve this problem.
The main thing to undertand is that page.media.images returns an array, so we can't filter this as a string.
So I just nested a match statement. I wonder if there's a one-liner solution.
{% for image in page.media.images %}
{% if image.html matches '/.*sponsor.*$/' %}
<br>{{ image.html }}
{% endif %}
{% endfor %}

How to pass the current context to include in Twig?

Say I have the following headline.twig partial:
<h2>{{ headline }}</h2>
and I want to include it in two places, once as:
<% for article in teasers %>
{{ include('headline.twig') }}
<% endfor %>
And then simply:
{{ include('headline.twig') }}
Is it possible to pass an include tag or function its context, so that the include "knows" that in the first instance the headline variable is actually article.headline?
I'm looking for a systematic way to do this, not with something like
{{ include('headline.twig', {headline: article.headline}) }}
If you want headline to be in the main context of your included file in all cases, you can do something like this:
{% for article in teasers %}
{% set headline = article.headline %}
{{ include('headline.twig') }}
{% endfor %}
But this will overwrite any existing headline variable in your current context if you're re-setting it this way (and risk to repeat 2 times the last iteration of teasers.article.headline).
The best solution if you want to keep your current context AND overwrite headline variable is to use the merge filter:
{% for article in teasers %}
{{ include('headline.twig', _context|merge({headline: article.headline})) }}
{% endfor %}
By default whole context is passed to included template.
So it will work in headline.twig:
<h2>{{ article.headline }}</h2>
And then in main template you only call:
{% include('headline.twig') %}
But article variable must be defined in moment of calling include.

Resources