improve documentation for embed tag

This commit is contained in:
literal
2012-05-10 03:10:48 +03:00
parent 87766410dd
commit b11412efd8
+85 -63
View File
@@ -4,64 +4,82 @@
.. versionadded:: 1.8 .. versionadded:: 1.8
The ``embed`` tag was added in Twig 1.8. The ``embed`` tag was added in Twig 1.8.
The ``embed`` statement allows you to embed a template instead of including it The ``embed`` tag combines the behaviour of :doc:`include<include>` and
from an external file (like with the ``include`` statement): :doc:`extends<extends>`.
It allows you to include another template's contents, just like ``include``
does. But it also allows you to override any block defined inside the
included template, like when extending a template.
Think of an embedded template as a "micro layout skeleton".
.. code-block:: jinja .. code-block:: jinja
{% embed "sidebar.twig" %} {% embed "teasers_skeleton.twig" %}
{% block content %} {# These blocks are defined in "teasers_skeleton.twig" #}
Some content for the sidebar {# and we override them right here: #}
{% block left_teaser %}
Some content for the left teaser box
{% endblock %}
{% block right_teaser %}
Some content for the right teaser box
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}
As it's not easy to understand in which circumstances it might come in handy, The ``embed`` tag takes the idea of template inheritance to the level of
let's take an example; imagine a base template shared by many pages with a content fragments. While template inheritance allows for "document skeletons",
single block: which are filled with life by child templates, the ``embed`` tag allows you to
create "skeletons" for smaller units of content and re-use and fill them
anywhere you like.
Since the use case may not be obvious, let's look at a simplified example.
Imagine a base template shared by multiple HTML pages, defining a single block
named "content":
.. code-block:: text .. code-block:: text
┌─── Page n ──────────────────────────┐ ┌─── page layout ─────────────────────┐
│ │ │ │
│ ┌─────────────────────┐ │ │ ┌── block "content" ──┐ │
│ │ │ │
│ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ (child template to │ │
│ │ put content here) │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ └─────────────────────┘ │ │ └─────────────────────┘ │
│ │ │ │
└─────────────────────────────────────┘ └─────────────────────────────────────┘
Some pages (page 1, 2, ...) share the same structure for the block: Some pages ("foo" and "bar") share the same content structure -
two vertically stacked boxes:
.. code-block:: text .. code-block:: text
┌─── Page 1 & 2 ──────────────────────┐ ┌─── page layout ─────────────────────┐
│ │ │ │
│ ┌── Base A ───────────┐ │ │ ┌── block "content" ──┐ │
│ │ ┌── content1 ─────┐ │ │ │ │ ┌─ block "top" ───┐ │ │
│ │ │ content for p1 │ │ │ │ │ │ │ │ │
│ │ └─────────────────┘ │ │ │ │ └─────────────────┘ │ │
│ │ ┌── content2 ─────┐ │ │ │ │ ┌─ block "bottom" ┐ │ │
│ │ │ content for p1 │ │ │ │ │ │ │ │ │
│ │ └─────────────────┘ │ │ │ │ └─────────────────┘ │ │
│ └─────────────────────┘ │ │ └─────────────────────┘ │
│ │ │ │
└─────────────────────────────────────┘ └─────────────────────────────────────┘
While other pages (page a, b, ...) share a different structure for the block: While other pages ("boom" and "baz") share a different content structure -
two boxes side by side:
.. code-block:: text .. code-block:: text
┌─── Page a, b ───────────────────────┐ ┌─── page layout ─────────────────────┐
│ │ │ │
│ ┌── Base B ───────────┐ │ │ ┌── block "content" ──┐ │
│ │ ┌───────┐ ┌───────┐ │ │ │ │ │ │
│ │ ┌ block ┐ ┌ block ┐ │ │
│ │ │"left" │ │"right"│ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ │content│ │content│ │ │
│ │ │a, ... │ │b, ... │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ └───────┘ └───────┘ │ │ │ │ └───────┘ └───────┘ │ │
│ └─────────────────────┘ │ │ └─────────────────────┘ │
@@ -70,64 +88,68 @@ While other pages (page a, b, ...) share a different structure for the block:
Without the ``embed`` tag, you have two ways to design your templates: Without the ``embed`` tag, you have two ways to design your templates:
* Create two base templates (one for 1, 2, ... blocks and another one for a, * Create two "intermediate" base templates that extend the master layout
b, ... blocks) to factor out the common template code, then one template template: one with vertically stacked boxes to be used by the "foo" and
for each page that inherits from one of the base template; "bar" pages and another one with side-by-side boxes for the "boom" and
"baz" pages.
* Embed each custom page content directly into each page without any use of * Embed the markup for the top/bottom and left/right boxes into each page
external templates (you need to repeat the common code for all templates). template directly.
These two solutions do not scale well because they each have a major drawback: These two solutions do not scale well because they each have a major drawback:
* The first solution makes you create many external files (that you won't * The first solution may indeed work for this simplified example. But imagine
re-use anywhere else) and so it fails to keep your templates readable (many we add a sidebar, which may again contain different, recurring structures
code and content are out of context); of content. Now we would need to create intermediate base templates for
all occurring combinations of content structure and sidebar structure...
and so on.
* The second solution makes you duplicate some common code from one template * The second solution involves duplication of common code with all its negative
to another (so it fails to obey the "Don't repeat yourself" principle). consequences: any change involves finding and editing all affected copies
of the structure, correctness has to be verified for each copy, copies may
go out of sync by careless modifications etc.
In such a situation, the ``embed`` tag fixes all these issues. The common code In such a situation, the ``embed`` tag comes in handy. The common layout
can be factored out in base templates (as in solution 1), and the custom code can live in a single base template, and the two different content structures,
content is kept in each page (as in solution 2): let's call them "micro layouts" go into separate templates which are embedded
as necessary:
Page template ``foo.twig``:
.. code-block:: jinja .. code-block:: jinja
{# template for pages 1, 2, ... #} {% extends "layout_skeleton.twig" %}
{% extends page %} {% block content %}
{% embed "vertical_boxes_skeleton.twig" %}
{% block base %} {% block top %}
{% embed "base_A.twig" %} Some content for the top box
{% block content1 %}
Content 1 for page 2
{% endblock %} {% endblock %}
{% block content2 %} {% block bottom %}
Content 2 for page 2 Some content for the bottom box
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}
{% endblock %} {% endblock %}
And here is the code for ``base_A.twig``: And here is the code for ``vertical_boxes_skeleton.twig``:
.. code-block:: jinja .. code-block:: html+jinja
Some code <div class="top_box">
{% block content1 %}
Top box default content
{% endblock %}
</div>
{% block content1 %} <div class="bottom_box">
Some default content {% block content2 %}
{% endblock %} Bottom box default content
{% endblock %}
</div>
Some other code The goal of the ``vertical_boxes_skeleton.twig`` template being to factor
out the HTML markup for the boxes.
{% block content2 %}
Some default content
{% endblock %}
Yet some other code
The goal of the ``base_a.twig`` base template being to factor out the ``Some
code``, ``Some other code``, and ``Yet some other code`` parts.
The ``embed`` tag takes the exact same arguments as the ``include`` tag: The ``embed`` tag takes the exact same arguments as the ``include`` tag: