[FR] give include an optional endinclude
In our project (Craft CMS) we have some common html patterns, which would ideally be wrapped around user content based on a "style" selection. E.g. an image gallery which either appears as slides or as thumbnails based on the surrounding html.
For this purpose we would like to create partials, which contain the different patterns / surrounding html. Ideally we would include the patterns AROUND the user generated content.
There are multiple ways to handle this with TWIG, like
- using
includeand pass the content as a variable - using
embedand passing the content as a block - using
applyand a specialwrapincfilter(wrap-include) we created as extension, which workarounds that requirement:
The main file:
{% apply wrapincfilter('wrapinc-include', {class: 'turbo'}) %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endapply %}
wrapinc-include:
<div class="{{ class }}">
{{ _wrapped }}
</div>
- But by far the nicest way for us would be this:
{% include 'wrapinc-include' with {class: 'turbo'} %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endinclude %}
The wrapped content should be provided as some reserved-name variable (or any other best practice) to the included file.
Conclusion: The Feature Request is: give {% include %} an optional {% endinclude %}
A tag that sometimes has a body and a closing tag and sometimes does not have it, without any difference in the opening tag creates an ambiguous syntax. So this is a no-go.
Well the set tag works that way, so the difference must the = following the variable name, right?
Options would be to give it an extra attribute, like 'with-body', an attribute to specify the var name for the body or create a new tag for it.
- Variant 1a:
{% include 'wrapinc-include' with-body with {class: 'turbo'} %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endinclude %}
- Variant 1b:
{% include 'wrapinc-include' body='_wrapped' with {class: 'turbo'} %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endinclude %}
- Variant 2:
{% wrapinclude 'wrapinc-include' with {class: 'turbo'} %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endwrapinclude %}
I'd prefer 1b.
Any further ideas or feedback appreciated.
In case of the {% set %}, the presence of the = followed by an expression in the opening tag is indeed the thing doing the switch between the 2 syntaxes.
OK. I understand. Do you see any necessity for my use case at all?
Because my suggestions from the last post would all have distinctions to allow this non-ambiguous syntax.
My initial suggestions to work with apply and a "wrapincfilter" does not work, because TWIG first expects an endapply before interpreting any other TWIG code. And include with a variable or embed are not as nice.
I think embed is the best for your use-case. It allows to override some blocks of the included template.
{# main.twig #}
{% embed "included.twig" with { class: 'turbo' } %}
{% block body %}
This is wrapped. Today's date: {{ 'now'|date('d.m.Y') }}
{% endblock %}
{% endembed %}
{# included.twig #}
<div class="{{ class }}">
{{ block('body') }}
</div>
The only difference with your "by far the nicest way" is that you need the {% block body %} tag to name the block, instead of a variable _wrapped named by convention.
yes, thats a good solution, thank you!