Skip to content

Component Composition

When to Use

Use this when including one component in another, deciding between include(), embed, or render arrays, or nesting components.

Decision

Method Use Case When to Use
include() Simple component inclusion Props-only components
{% embed %} Populating slots via Twig blocks Components with slots that need custom content
Render arrays Programmatic rendering PHP code (preprocessing, controllers, forms)
Nested components Complex compositions Building organisms from molecules

Pattern

include() Function (Most Common):

{# Simple inclusion #}
{{ include('my_theme:button', {
  text: 'Click Me',
  variant: 'primary',
  disabled: false
}) }}

{# With context isolation (recommended) #}
{{ include('my_theme:button', {
  text: 'Save',
  variant: 'primary'
}, with_context = false) }}

embed Tag (Only for Slots):

{% embed 'my_theme:card' with {
  title: node.label,
  variant: 'featured'
} only %}

  {% block content %}
    {{ content.body }}
    {{ include('my_theme:button', {
      text: 'Read More',
      url: node.url
    }) }}
  {% endblock %}

  {% block footer %}
    {{ content.field_tags }}
  {% endblock %}

{% endembed %}

Render Arrays (Programmatic):

$build = [
  '#type' => 'component',
  '#component' => 'my_theme:card',
  '#props' => [
    'title' => $node->label(),
    'variant' => 'featured',
  ],
  '#slots' => [
    'content' => $node->body->view('teaser'),
    'footer' => $node->field_tags->view('compact'),
  ],
];

Common Mistakes

  • Wrong: Using embed for props-only components → Right: Use include() (simpler, less overhead)
  • Wrong: Not using with_context = falseRight: Prevent variable leakage for predictable components
  • Wrong: Hardcoding child components → Right: Use slots for flexibility

See Also