Skip to main content

Templating

Flare's content elements render Twig templates. In current Flare versions, the flare variable in those templates is an Engine object. To access list or reader data, create a view explicitly in Twig with flare.createView.

tip

Use the bundled templates as your starting point. They reflect the current runtime API.

Current Templating Model

Older Flare documentation referred to Twig helpers such as flare_form(...), flare_make_list(...), and direct access to flare.entries. That is no longer the current model.

Today:

  • flare is the engine injected by the content element controller
  • flare.createView creates the runtime view object for the current context
  • list templates work with an InteractiveView
  • reader templates work with a ValidationView

Template Locations

Bundled Templates

The bundled templates live in:

vendor/heimrichhannot/contao-flare-bundle/contao/templates/

The main content element templates are:

vendor/heimrichhannot/contao-flare-bundle/contao/templates/content_element/flare_listview.html.twig
vendor/heimrichhannot/contao-flare-bundle/contao/templates/content_element/flare_reader.html.twig

Related partials live in:

vendor/heimrichhannot/contao-flare-bundle/contao/templates/flare/

Custom Templates

To override or extend the provided templates, create Twig files in a Twig template directory of your Contao installation. Assuming there is a .twig-root file in contao/templates/, a typical structure looks like this:

contao/templates/content_element/{flare_listview,flare_reader}/my_variant.html.twig

You can then select the variant via the content element's customTpl field.

List View Templating

The default list template creates an interactive view first and then renders the filter form, entries, and paginator from that view.

contao/templates/content_element/flare_listview/my_variant.html.twig
{% extends "@Contao/content_element/flare_listview.html.twig" %}

{% set flare_list = flare.createView %}

{% block filter %}
{% set form = flare_list.form.createView %}

{{ form_start(form) }}
{{ form_widget(form) }}
<button type="submit">{{ 'submit'|trans({}, 'flare_form') }}</button>
{{ form_end(form) }}
{% endblock %}

{% block list %}
{% for entry in flare_list.entries %}
{% set href = flare_list.to(entry.id) %}

<article>
<h3>
{% if href %}
<a href="{{ href }}">{{ entry.headline ?? entry.title ?? '' }}</a>
{% else %}
{{ entry.headline ?? entry.title ?? '' }}
{% endif %}
</h3>
</article>
{% else %}
<p>No entries found.</p>
{% endfor %}
{% endblock %}

{% block pagination %}
{{ include('@Contao/flare/paginator.html.twig', {
paginator: flare_list.paginator
}) }}
{% endblock %}

Available Variables in List Templates

The list content element injects these template variables:

  • flare: the Engine
  • content_model: the tl_content model of the current content element
  • headline: the normalized Contao headline data

After creating the view with flare.createView, you typically work with:

  • flare_list.form: the Symfony form object
  • flare_list.entries: the current result set
  • flare_list.paginator: the paginator
  • flare_list.count: the total result count
  • flare_list.to(id): the reader URL for an entry, if configured
  • flare_list.model(id): the Contao\Model instance for a specific entry

Entries and Models

In list templates, flare_list.entries yields associative arrays for the current result set.

If you need access to the full model collection directly, use flare_list.models:

{% for model in flare_list.models %}
<h3>{{ model.headline ?? model.title ?? '' }}</h3>
{% endfor %}

If you need models only occasionally, you can still iterate over flare_list.entries and resolve a specific model from the current entry:

{% for entry in flare_list.entries %}
{% set model = flare_list.model(entry.id) %}
<h3>{{ model.headline ?? entry.headline ?? '' }}</h3>
{% endfor %}
note
  • Use flare_list.entries when the raw result data is sufficient.
  • If you only need models occasionally throughout the loop, using flare_list.model(entry.id) is perfectly fine.
  • If you need models throughout the whole loop, flare_list.models is the better choice than resolving each model individually.

Customizing the Filter Form

The filter form is a normal Symfony form. Create the form view from flare_list.form and apply form themes as usual.

{# {% set flare_list = flare.createView %} if not yet created #}
{% set form = flare_list.form.createView %}

You can access individual form fields by their field name. That field name is also used for the submitted query parameter. For example, if a field is named search, you can access it as form.search:

{% set search_field = form.search %}
{{ form_row(search_field) }}
{% block filter %}
{% set flare_list = flare.createView %}
{% set form = flare_list.form.createView %}

{% form_theme form with [
'bootstrap_5_layout.html.twig',
'form/my_symfony_form_theme.html.twig',
] %}

{{ form_start(form) }}

{% set search_field = form.search %}

<div class="my-form-fields">
<div class="my-custom-search-field">
{{ form_row(search_field) }}
</div>
{{ form_rest(form) }}
</div>

{% block submit %}
<button type="submit">Apply filter</button>
{% endblock %}

{% block reset %}
<button type="reset" class="visually-hidden-focusable">Reset filter</button>
{% endblock %}

{{ form_end(form) }}
{% endblock %}
info

Because form themes are standard Symfony form themes, place them in templates/form/ relative to the project root, not in the Contao templates directory.

Reader Templating

The reader content element renders a single model. Its default template extends the same base template as the list view, but works with reader-specific variables.

contao/templates/content_element/flare_reader/my_variant.html.twig
{% extends "@Contao/content_element/flare_reader.html.twig" %}

{% block content %}
<article>
<h1>{{ model.headline ?? model.title ?? '' }}</h1>

{% if model.teaser %}
<div>
{{ model.teaser|raw }}
</div>
{% endif %}
</article>
{% endblock %}

Available Variables in Reader Templates

The reader content element injects these variables:

  • flare: the Engine
  • flare_reader: the ValidationView
  • model: the resolved Contao\Model for the current reader item
  • content_model: the tl_content model of the current content element
  • headline: the normalized Contao headline data
  • comments: optional comments data when the comments integration attaches it

The reader template can also use flare_reader.to(id) if you need to generate reader links from the validation view.

Block Structure

These are the main blocks available for extension.

Base Template

@Contao/flare/_flare_base.html.twig defines:

  • wrapper
  • headline
  • content
  • footer

List Template

@Contao/content_element/flare_listview.html.twig adds:

  • content_start
  • filter
  • list
  • pagination
  • content_end

Reader Template

@Contao/content_element/flare_reader.html.twig mainly customizes:

  • content
  • footer

Paginator Templates

Flare ships several paginator templates.

Default paginator

{{ include('@Contao/flare/paginator.html.twig', {
paginator: flare_list.paginator
}) }}

The default paginator supports use_default_styles:

{{ include('@Contao/flare/paginator.html.twig', {
paginator: flare_list.paginator,
use_default_styles: true
}) }}

Bootstrap 5 variants

Flare also ships:

  • @Contao/flare/paginator/bs5.html.twig
  • @Contao/flare/paginator/bs5_extended.html.twig

These are useful if you want Bootstrap-compatible paginator markup instead of the default Flare-specific markup.

Comments Integration

The default reader template renders comments in its footer block if comments data is present:

{% block footer %}
{% if comments|default(false) %}
{{ include('@Contao/flare/comments/basic.html.twig', comments) }}
{% endif %}
{% endblock %}

Comments are not universally available. They are attached by Flare's comments integration when the current list and reader setup supports them.

Twig Helpers

Flare currently registers these Twig functions:

  • flare_content
  • flare_enclosure
  • flare_enclosure_files
  • flare_make_filter
  • flare_project
  • flare_copy_view
  • flare_schema_org

These are lower-level helpers for advanced use cases. They are not a replacement for the standard content-element templating workflow described above.

Migration Notes

When updating older custom templates:

  • replace flare_form(...) with flare.createView followed by flare_list.form.createView
  • replace direct flare.entries and flare.paginator access with properties on the created view
  • remove any use of flare_make_list(...), which is no longer part of the current Twig API
  • access all current list models via flare_list.models when you need the full collection