Component loader and pre-processor for Twig templates.
This was a shortcut taken to allow junior/intermediate Vue.js developers to quickly jump into huge legacy Symfony/Twig templates.
Its only purpose was to survive a big refactoring middle-step, allowing us to move forward with Vue.js and other more suited frontend languages.
If you still feel like this can help you, don't hesitate to contact post@barthy.koeln or create an issue.
Components can be used within regular Twig templates:
{# File: @components/Page/PHome/PHome.twig #}
{% extends '@components/Teamplate/TBase.twig' %}
{% block contents %}
<AButton
theme="primary"
label="{{ 'button.edit_entity'|trans }}"
/>
{% endblock %}
{# File: @components/Atom/AButton/AButton.twig #}
<button
type="button"
class="a-button -{{ props.theme|default('grey') }}"
>
{{ props.label }}
</button>
Props passed to your components can be either hard-coded strings (example: theme
), or variables and expressions (
example: level
). They will be scoped in the object props
.
<ALabel
theme="danger"
level="{{ errors|count * 10 }}"
/>
Blocks can be defined and used like in any regular twig template. There are a few syntactic helpers, though:
{# File: @components/Page/PHome/PHome.twig #}
{% extends '@components/Teamplate/TBase.twig' %}
{% block contents %}
<AButton theme="primary">
{{ 'button.edit_entity'|trans }}
</AButton>
{% endblock %}
{# File: @components/Atom/AButton/AButton.twig #}
<button
type="button"
class="a-button -{{ props.theme|default('grey') }}"
>
{% block AButton__default %}{% endblock %}
</button>
{# File: @components/Page/PHome/PHome.twig #}
{% extends '@components/Teamplate/TBase.twig' %}
{% block contents %}
<AButton theme="primary">
<block #icon>
<span>×</span>
</block>
<block #label>{{ 'button.edit_entity'|trans }}</block>
</AButton>
{% endblock %}
{# File: @components/Atom/AButton/AButton.twig #}
<button
type="button"
class="a-button -{{ props.theme|default('grey') }}"
>
{% if block('icon') is defined %}
<i class="a-button_icon">{{ block('icon')|raw }}</i>
{% endif %}
<span class="a-button__label">
{% block label %}{% endblock %}
</span>
</button>
Since this component loader works as a pre-processor, it's goal is to accept subjectively easier/better syntax, and to pass valid Twig syntax to the Twig engine.
Understanding what is transpiled to what can help you master this new syntax:
- Include: Component without blocks
- Embed: Component with blocks
- String parameters: properties without
{{ … }}
- Variables and expressions: properties with
{{ … }}
TCT In:
<AButton theme="primary">
<block #icon>
<span>×</span>
</block>
<block #label>{{ 'button.edit_entity'|trans }}</block>
</AButton>
<AIcon name="{{ random_name() }}"/>
Twig Out (Simplified):
{% embed '@components/Atom/AButton/AButton.twig' with { props: { theme: "primary" } } %}
{% block icon %}
<span>×</span>
{% endblock %}
{% block label %}
{{ 'button.edit_entity'|trans }}
{% endblock %}
{% endembed %}
{% include '@components/Atom/AIcon/AIcon.twig' with { props: { name: random_name() } } %}
This preprocessor aims to make developing and reviewing Twig templates easier and faster.
There is not enough visual distinction between control
statements: {% if … %}
, {% for … %}
, {% set … %}
and markup/composition: {% include … %}
, {% embed … %}
.
Customizing the syntax doesn't quite cut it for me.