web-dev-qa-db-de.com

Überschreiben von Blöcken in enthaltenen Twig-Vorlagen

Gibt es im Allgemeinen einen "guten" Weg, um diese Funktionalität zu erreichen? Ich habe über das "use" -Tag gelesen, das bisher die beste Option zu sein scheint, aber ich mag es immer noch nicht, dass ich keine HTML-Dateien von außen einführen kann, sondern nur Blöcke.

Ich werde im folgenden Beispiel das 'include' -Tag verwenden, um die Absicht zu veranschaulichen, die ich zu beschreiben versuche.

#base.html.twig
{% include 'elements/header.html.twig' %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}

#header.html.twig
<h1>This is my header</h1>
{% block page_title %} Default Page Title {% endblock %}

#index.html.twig
{% extends 'layouts/base.html.twig' %}
{# I want to be able to do this somehow #}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
44
bruchowski

Ich habe eine Lösung gefunden. Verwenden Sie die Funktion block (), um den Blockinhalt des untergeordneten Objekts abzurufen und als Variable in der include-Anweisung an header.html.twig zu übergeben:

#base.html.twig
{% include 'elements/header.html.twig' with {page_title: block('page_title')} %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}

#header.html.twig
<h1>This is my header</h1>
{% if page_title is empty %}
Default Page Title
{% else %}
{{ page_title }}
{% endif %}

#index.html.twig
{% extends 'layouts/base.html.twig' %}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
53
Webberig

Ich habe eine gute und echte -Lösung gefunden, die die -Dokumentation für das embed -Tag liest. Ich verwende Twig 2.0 in Symfony 4.

Meine Struktur

#templates/base.html.twig
{% block navbar %}
    <nav>
    {% block menu %}
        {% include '_menu' %}
    {% endblock menu %}
    </nav>
{% endblock navbar %}
{% block content %}
    {# several blocks defined #}
    {% block footer '' %}
{% endblock content %}

#templates/_menu.html.twig
<ul>
    {% block sub_app_menu_itens %}
        <li>Main App Menu Item</li>
    {% endblock sub_app_menu_itens %}
    <li>Menu item</li>
    <li>Another menu item</li>
    <li>Yet another menu item</li>
</ul>

Mit dem obigen Code ist beim Erstellen meines index.html.twig der einzige Code, der zum Anzeigen der Standardeinstellungen erforderlich ist

#templates/index.html.twig
{% extends 'base.html.twig' %}

und überschriebene Blöcke überschreiben . Wenn ich jedoch eine andere Seite erstellen muss, die diese Skelette verwendet, wenn ich versuche, block sub_app_menu_itens in einer anderen enthaltenen _partial-Vorlage zu überschreiben, funktioniert dies nicht. <li>Main App Menu Item</li> wird immer angezeigt und niemals überschrieben (Code oben)

#templates/subapp/index.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ 'agencia.homepage'|trans }}{% endblock %}
{% block menu %}
    {% include 'subapp/_menu.html.twig' %}
{% endblock menu %}
{% block user_content %}Content Here{% endblock %}

#templates/subapp/_menu.html.twig
{% extends '_menu.html.twig' %}
{% block sub_app_menu_itens %}
        <li>SubApp Menu Item</li> 
{% endblock sub_app_menu_itens %}

<li>SubApp Menu Item</li> wird nie angezeigt. Habe eine Menge Dinge wie extends und sogar Bedingungen ohne Glück versucht.

Die Lösung

Das embed -Tag löst die zu überschreibenden untergeordneten Teilvorlagenblöcke auf.

#templates/subapp/index.html.twig
{% block menu %}
    {% embed '_menu.html.twig' %}
        {% block sub_app_menu_itens %}
            {% include 'subapp/_menu.html.twig' %}
        {% endblock sub_app_menu_itens %}
    {% endembed %}
{% endblock menu %}

Und die Vereinfachung der _partial-Vorlage, um nur die HTML-Datei zu benötigen

#templates/subapp/_menu.html.twig 
    <li>SubApp Menu Item</li> 

Jetzt wird <li>SubApp Menu Item</li> an der richtigen Stelle der _menu-Vorlage angezeigt.

Wenn Sie in Ebenen denken, funktioniert eine include wie eine untergeordnete Ebene (analysiert) und alle Dinge werden nur auf derselben Ebene überschrieben, sodass include das Überschreiben in einem anderen Include nicht zulässt. Stattdessen werden embed-Vorlagen auf die gleiche Ebene gebracht (nicht analysiert), sodass Sie die Dinge überschreiben können.

3
Marcos Regis

Es kann gemacht werden. Hier ist meine Lösung für das Problem, indem Sie eine Variable an die Ansicht übergeben.

#layout.twig
{% if sidebar is empty %}
    This is the default sidebar text.
{% else %}
    {% block sidebar %}{% endblock %}
{% endif %}
{% block content %}{% endblock %}

#index.twig
{% extends "layout.twig" %}
{% block sidebar %}
    This is the sidebar. It will override the default text.
{% endblock %}

{% block content %}
    This is the content.
{% endblock %}

#index.php (SlimPHP)
$app->render('index.twig', ['sidebar' => true]);

Da ich SlimPHP benutze, benutze ich sidebar an die Ansicht. Dies kann durch die Verwendung verschiedener Variablen, die an die Ansicht übergeben werden, erweitert werden, sodass Sie sidebar1, sidebar2 usw. auswählen können.

1
kacperek

Ich bekam es mit einem sehr einfachen Hack zu arbeiten:

Im Prinzip verhält es sich so, weil es ohne einen {% extends "foo.html.twig" %} die Blöcke nicht versteht und sie einfach an Ort und Stelle rendert.

Also lass uns erweitern ... nichts:

{% extends "nothing.html.twig" %}

Dieses Nichts ist wirklich nur ein Block:

# nothing.html.twig
{% block main %}
{% endblock %}

Die einzige Sache ist, dass Sie alles in einen Block einwickeln müssen, diesen gefälschten "Haupt" -Block.

0
lipsumar