Multi-level template inheritance?

Hi at all,

I am setting up the general template structure of my web application and want to know how to achieve an effective inheritance to follow the DRY (Don’t Repeat Yourself) principle.

As I will have different areas in my application (frontend/backend) I would like to create several base layouts, e.g. Frontend.html and Backend.html that each contain a placeholder for the content (that will be rendered by the action).

How can I achieve that those two layout files inherit from a general HTML structure with shared meta tags, favicon, general css/js and so on?

Perhaps I am spoilt by Symfony & Twig but there you can do something like that:

base.html.twig:

<!DOCTYPE html>
<html>
    <head>
        {% block meta %}default meta tags{% endblock %}
        <title>{% block title %}default title{% endblock %}</title>
        {% block stylesheets %}default stylesheets{% endblock %}
    </head>
    <body>
        {% block structure %}{% endblock %}
        {% block javascripts %}default javascripts{% endblock %}
    </body>
</html>

frontend.html.twig:

{% extends '::base.html.twig' %}

{% block title %}my frontend title{% endblock %}

{% block stylesheets %}
    //uses the parent stylesheets and adds frontend css
    {{ parent() }}    
    <link href="path/to/frontend.css" type="text/css" rel="stylesheet" />
{% endblock %}

{% block structure %}
<my>
    <frontend>
        <structure>
            {% block content %}my default frontend content{% endblock %}
        </structure>
    </frontend>
</my>
{% endblock %}

edit.html.twig (rendering is called by action controller)

{% extends '::frontend.html.twig' %}

{% block stylesheets %}
    //uses the parent stylesheets and adds edit css
    {{ parent() }}
    <link href="path/to/edit.css" type="text/css" rel="stylesheet" />
{% endblock %}

{% block content %}
<my>
    <edit>
        <structure>
            <form>...</form>
        </structure>
    </edit>
</my>
{% endblock %}

Is such a flexible and granular approach (to inherit a layout from a layout (from a layout…)) also somehow possible with Fluid?

I tried to define a layout file “Base” in a layout file “Frontend” but that did not work.
It seems to me that you can only define a single layout file in the template files which are called by the action controller or did I miss something in the documentation?

Thanks in advance!

Hi Katharina,

as far as I know there’s no inheritance in Fluid-Templates but as far as I understand something like you mention could also be accomplished using partials.
I might have misunderstood you but I guess that could work. An (bit older) example can be found here: http://www.layh.com/typo3-flow-step-by-step/add-a-navigation-using-partials/

Regards,
David

Hi David,

this is my approach using partials.
The zone switch seems rather messy to me (especially in terms of further extensibility) besides facing a considerably huge file.

Base.html:

<!DOCTYPE html>
<html>
<head>...</head>
<body>
...
<f:if condition="{zone} == 'Frontend'">
    <f:then>
        <f:render partial="Navbar"></f:render>

        <div class="container">

            <div class="row row-offcanvas row-offcanvas-right">

                <div class="col-xs-12 col-sm-9">
                    <f:render section="Content"></f:render>
                </div>

                <f:render partial="Sidebar"></f:render>
            </div>
            <hr>
            <f:render partial="Footer"></f:render>

        </div>
    </f:then>
    <f:else>
        ...
        //backend structure with sections "Navbar", "Content", "Footer"... at other positions or not included
        <f:render section="Content"></f:render>
        ...
    </f:else>
</f:if>
...
</body>

Each of my controllers will then either extend a FrontendController or BackendController class where the “zone” variable is assigned centrally.

Hi Katharina,

I’m no sure if I understand what you’re trying to do.
If there are different templates for frontend and backend I think it would be better to create two different templates for frontend and backend and then use partials if there are parts that occur in both templates.

Maybe one of the other guys knows Symfony better and can help you more than I can.

Regards,
David

You can define the used Layout either in your templates (http://flowframework.readthedocs.org/en/latest/TheDefinitiveGuide/PartIII/Templating.html#using-a-layout), inside the controllers or via the Views.yaml configuration (http://flowframework.readthedocs.org/en/latest/TheDefinitiveGuide/PartIII/ModelViewController.html?highlight=views%20configuration#configuring-views-through-views-yaml), where you can set the views “layoutPathAndFilename” setting. So you could for example configure that your FrontController will always render the Frontend.html layout, and the BackendController the Backend.html layout. Then your action templates actually don’t have to worry about which layout they should be rendered in.

From there it’s just a matter of creating partials for the common parts as david suggested, like this:

Frontend.html:

<html>
<head>
    <f:render partial="Common/Styles" />
   <style>frontend styles</style>
</head>
<body>
   <f:render partial="Common/Header" />

   <frontend>
        <structure>
            <f:render section="templateSection1" />
        </structure>
   </frontend>

   <script>frontend scripts...</script>
   <f:render partial="Common/Scripts" />
</body>
</html>