Following up on the multi-column Paragraphs pattern, here’s how to build a Bootstrap Carousel using the same approach — a parent Paragraph bundle that holds multiple child “slide” Paragraph bundles, all rendered through a single Twig template.
The setup
Two Paragraph bundles:
- Carousel (parent) — holds a multi-value Paragraph reference field pointing to Slide bundles
- Slide (child) — holds an image field and an optional caption text field
The parent Paragraph template handles the carousel scaffold; the child template handles the individual slide.
The parent template
{# paragraph--carousel.html.twig #}
<div id="carousel-{{ paragraph.id.value }}" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
{% for key, item in content.field_slides %}
{% if key|first != '#' %}
<li data-target="#carousel-{{ paragraph.id.value }}"
data-slide-to="{{ loop.index0 }}"
class="{{ loop.first ? 'active' : '' }}"></li>
{% endif %}
{% endfor %}
</ol>
<div class="carousel-inner">
{% for key, item in content.field_slides %}
{% if key|first != '#' %}
<div class="item {{ loop.first ? 'active' : '' }}">
{{ item }}
</div>
{% endif %}
{% endfor %}
</div>
<a class="left carousel-control" href="#carousel-{{ paragraph.id.value }}" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-{{ paragraph.id.value }}" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
The key trick is the key|first != '#' check to filter out Twig render array metadata keys (the # properties) and only iterate over the actual slide items.
Why Paragraphs for this
The alternative — a multi-value image field directly on the node — gives you less editor control. With Paragraphs, each slide can carry its own fields (caption, link, alt text, CTA button) without polluting the node field structure. And the template pattern scales: add a new field to the Slide bundle, and it appears in every carousel on the site automatically.