Access a streamfield block's index within its template

1,047 views
Skip to first unread message

Crew sCam

unread,
Feb 15, 2016, 11:47:49 AM2/15/16
to Wagtail support
Hey there!

First up thank you very much indeed to all the authors and contributors of Wagtail. It's very, very cool!

My question is whether anyone would be aware of a way to get the current index of a template based 'for loop' that is generating the Streamfield blocks from INSIDE the block's template.

Our use case is that every FIRST block on a page needs an extra little bit of markup (a downward scroll arrow). A CSS class on the containing element isn't really enough - we don't really want the extraneous markup 'hidden', we ideally want to omit it entirely.

Any help greatly appreciated,

Thanks! Si

Matthew Westcott

unread,
Feb 15, 2016, 12:33:35 PM2/15/16
to wag...@googlegroups.com
Hello Si,
There's no way to do this I'm afraid - the block's template only receives the block value, which has no knowledge of its position in the list. (In many cases, that value will be a simple data type such as a string.) We could possibly update this so that the template is passed the index as well, but I'm not sure it would be good design to do so - block rendering should really work the same regardless of whether the block is part of a list or not (e.g. a child of a StructBlock). In this case, I'd say that "does this block get an arrow or not" is behaviour relating to the sequence, rather than the individual blocks, so it would be more appropriate for the outer template to handle this, as in:

<ul>
{% for block in page.body %}
<li>
{% if forloop.first %}<a href="#">down</a>{% endif %}
{{ block }}
</li>
{% endfor %}
</ul>

- which does mean that the portion rendered by the {{ block }} is probably smaller than you were hoping for (e.g. it can't include the <li> tag), but I think that's a good thing from the point of view of keeping the overall structural markup separate from the individual block templates.

Cheers,
- Matt

Crew sCam

unread,
Feb 15, 2016, 12:43:36 PM2/15/16
to Wagtail support
Hey!

Thanks for the swift reply :)

OK no worries - I'll see if I can find another way round the problem!

Cheers, sCam

David Nugent

unread,
Feb 21, 2016, 11:02:34 PM2/21/16
to Wagtail support
Actually I have hit a similar use case that needs something unique - like an index - for each block available in the template rendered in the {{ block }}.

I would like this to generate unique id elements in markup enclosing elements of the 'value' within the template, in my case to generate code that would support a bootstrap accordion block to allow collapsing and revealing text elements.

So +1 vote for the index from me.

Cheers
/d

Daniel Tate

unread,
Mar 12, 2018, 9:58:21 PM3/12/18
to Wagtail support
Any result on this, I know its a few years old but I have just run into this same problem

Matthew Westcott

unread,
Mar 12, 2018, 10:08:05 PM3/12/18
to wag...@googlegroups.com
Hi Daniel,

The recommended way of rendering blocks with their own templates is now the {% include_block %} tag, which provides a suitable mechanism for passing additional variables:

{% for block in page.body %}
{% include_block block with index=forloop.counter %} {# the block's template can now refer to the variable 'index' #}
{% endif %}

Cheers,
- Matt
> --
> You received this message because you are subscribed to the Google Groups "Wagtail support" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wagtail+u...@googlegroups.com.
> To post to this group, send email to wag...@googlegroups.com.
> Visit this group at https://groups.google.com/group/wagtail.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/wagtail/e74a8847-6db7-48a4-b31b-db8b8db6272b%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages