blob: 42e33b1955a7883c04fc9acfd649ce99b3407bb5 [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001``embed``
2=========
3
4The ``embed`` tag combines the behavior of :doc:`include<include>` and
5:doc:`extends<extends>`.
6It allows you to include another template's contents, just like ``include``
7does. But it also allows you to override any block defined inside the
8included template, like when extending a template.
9
10Think of an embedded template as a "micro layout skeleton".
11
12.. code-block:: twig
13
14 {% embed "teasers_skeleton.twig" %}
15 {# These blocks are defined in "teasers_skeleton.twig" #}
16 {# and we override them right here: #}
17 {% block left_teaser %}
18 Some content for the left teaser box
19 {% endblock %}
20 {% block right_teaser %}
21 Some content for the right teaser box
22 {% endblock %}
23 {% endembed %}
24
25The ``embed`` tag takes the idea of template inheritance to the level of
26content fragments. While template inheritance allows for "document skeletons",
27which are filled with life by child templates, the ``embed`` tag allows you to
28create "skeletons" for smaller units of content and re-use and fill them
29anywhere you like.
30
31Since the use case may not be obvious, let's look at a simplified example.
32Imagine a base template shared by multiple HTML pages, defining a single block
33named "content":
34
35.. code-block:: text
36
37 ┌─── page layout ─────────────────────┐
38
39 ┌── block "content" ──┐
40
41
42 (child template to
43 put content here)
44
45
46 └─────────────────────┘
47
48 └─────────────────────────────────────┘
49
50Some pages ("foo" and "bar") share the same content structure -
51two vertically stacked boxes:
52
53.. code-block:: text
54
55 ┌─── page layout ─────────────────────┐
56
57 ┌── block "content" ──┐
58 ┌─ block "top" ───┐
59
60 └─────────────────┘
61 ┌─ block "bottom"
62
63 └─────────────────┘
64 └─────────────────────┘
65
66 └─────────────────────────────────────┘
67
68While other pages ("boom" and "baz") share a different content structure -
69two boxes side by side:
70
71.. code-block:: text
72
73 ┌─── page layout ─────────────────────┐
74
75 ┌── block "content" ──┐
76
77 block block
78 "left" "right"
79
80
81 └───────┘ └───────┘
82 └─────────────────────┘
83
84 └─────────────────────────────────────┘
85
86Without the ``embed`` tag, you have two ways to design your templates:
87
88* Create two "intermediate" base templates that extend the master layout
89 template: one with vertically stacked boxes to be used by the "foo" and
90 "bar" pages and another one with side-by-side boxes for the "boom" and
91 "baz" pages.
92
93* Embed the markup for the top/bottom and left/right boxes into each page
94 template directly.
95
96These two solutions do not scale well because they each have a major drawback:
97
98* The first solution may indeed work for this simplified example. But imagine
99 we add a sidebar, which may again contain different, recurring structures
100 of content. Now we would need to create intermediate base templates for
101 all occurring combinations of content structure and sidebar structure...
102 and so on.
103
104* The second solution involves duplication of common code with all its negative
105 consequences: any change involves finding and editing all affected copies
106 of the structure, correctness has to be verified for each copy, copies may
107 go out of sync by careless modifications etc.
108
109In such a situation, the ``embed`` tag comes in handy. The common layout
110code can live in a single base template, and the two different content structures,
111let's call them "micro layouts" go into separate templates which are embedded
112as necessary:
113
114Page template ``foo.twig``:
115
116.. code-block:: twig
117
118 {% extends "layout_skeleton.twig" %}
119
120 {% block content %}
121 {% embed "vertical_boxes_skeleton.twig" %}
122 {% block top %}
123 Some content for the top box
124 {% endblock %}
125
126 {% block bottom %}
127 Some content for the bottom box
128 {% endblock %}
129 {% endembed %}
130 {% endblock %}
131
132And here is the code for ``vertical_boxes_skeleton.twig``:
133
134.. code-block:: html+twig
135
136 <div class="top_box">
137 {% block top %}
138 Top box default content
139 {% endblock %}
140 </div>
141
142 <div class="bottom_box">
143 {% block bottom %}
144 Bottom box default content
145 {% endblock %}
146 </div>
147
148The goal of the ``vertical_boxes_skeleton.twig`` template being to factor
149out the HTML markup for the boxes.
150
151The ``embed`` tag takes the exact same arguments as the ``include`` tag:
152
153.. code-block:: twig
154
155 {% embed "base" with {'foo': 'bar'} %}
156 ...
157 {% endembed %}
158
159 {% embed "base" with {'foo': 'bar'} only %}
160 ...
161 {% endembed %}
162
163 {% embed "base" ignore missing %}
164 ...
165 {% endembed %}
166
167.. warning::
168
169 As embedded templates do not have "names", auto-escaping strategies based
170 on the template name won't work as expected if you change the context (for
171 instance, if you embed a CSS/JavaScript template into an HTML one). In that
172 case, explicitly set the default auto-escaping strategy with the
173 ``autoescape`` tag.
174
175.. seealso::
176
177 :doc:`include<../tags/include>`