2

I'm fiddling around with Twig and CraftCMS, trying to create a component-based structure... of sorts.

All good so far, except this one thing I got stuck on.


Here's an excerpt from my main layout:

<body>
    {% include 'components/header.twig' %}

    {% block content %}
        woops...
    {% endblock %}

    {% include 'components/footer.twig' %}
</body>

Which currently works.

But, I'd like to do something like this...

<body>
    {% include 'components/header.twig' %}
    {% include 'components/main-wrapper.twig' %}
    {% include 'components/footer.twig' %}
</body>

Where the main-wrapper.twig is like this, for example:

<main class="main">
    {% block content %}
        woops... 
    {% endblock %}
</main>

But it does not work. "woops..." from main-wrapper.twig is displayed.



I've tried a different route without success as well:

<body>
    {% include 'components/header.twig' %}

    {% embed 'components/main-wrapper.twig' %}
        {% block children %}
            {# I want to have the block content here... #}
        {% endblock %}
    {% endembed %}

    {% include 'components/footer.twig' %}
</body>

Where the main-wrapper.twig has a block named children instead... but no dice.



It does appear that what I'm trying to do is not possible, which is why I'm asking here as a last resort :)




EDIT:

For those interested, here's what I ended up with, stripped for clarity:

{# default.twig - default layout #}

<!DOCTYPE html>
<html>
    <head>
       ...
    </head>
    <body>
        {% include 'components/header.twig' %}
        {% block wrappedContent %}{% endblock %}
        {% include 'components/footer.twig' %}
    </body>
</html>


{# regular.twig - base page referred in the admin panel #}

{% extends "components/main.twig" %}

{% block content %}
    --- stuff for a page ---
{% endblock %}


{# main.twig - wrapper component! :D #}

{% extends "layouts/default.twig" %}

{% block wrappedContent %}
    <main class="main">
        <div class="main__wrapper">
            {% block content %}
                wooops...
            {% endblock %}
        </div>
    </main>
{% endblock %}

2 Answers 2

3

Unfortunately, there's no way around having the {% block %} tag somewhere in the template that's being extended. In other words, your main layout template it's going to have {% block %} tags.

However, you can use the {% embed %} tag to "wrap" a block in a third template (e.g. "components/main-wrapper.html"):

{# base.html #}
<body>
    {% block main %}{% endblock %}
</body>

{# components/main-wrapper.html #}
<main id="main-wrapper" role="main">
    <div class="container">
        {% block content %}{% endblock %}
    </div>
</main>

{# news/entry.html #}
{% extends 'base.html' %}

{% block main %}
    {% embed 'components/main-wrapper' %}
        {% block content %}This is my awesome main content{% endblock %}
    {% endembed %}
{% endblock %}

The result will look like this:

<body>
    <main id="main-wrapper" role="main">
        <div class="container">This is my awesome main content</div>
    </main>
</body>
1
  • Quite similar method to what I figured out just by fiddling around! Instead of embedding, I managed to use a {% block wrappedContent %} in the layout, where the {% block content %} is swallowed inside the main-wrapper.twig :)
    – Ole
    Commented Mar 10, 2016 at 18:46
4

It seems to be what you need is Twigs extend functionality. What you have here is a very common template structure so there is nothing out of the ordinary!

Firstly, going from your code I'd recommend your main layout template file looks something like this. The idea here being that these elements will not change for each page, but the content or information displayed inside them will. This template file is where you would also load in your CSS, Javascript etc.

<body>
    {% include 'components/header' %}

    <main class="main">
        {% block content %}{% endblock %}
    </main>

    {% include 'components/footer' %}
</body>

Say you have a page that will sit on www.yoursite.co.uk/about. You could create a template file in your templates folder called about.twig, and to use your base template file it would look something like this:

{% extends "path/to/main/layout" %}

{% block content %}

    <p>The content for your about page</p>

{% endblock %}

Hope that clears it up for you!

2
  • 1
    Afraid you either missed my point, or that my point is unclear to being with... In your first code block, where the <body> tag is in, I'm trying to avoid having a {% block content %} inside it. I want the {% block content %} to be inside an included component, you see? :)
    – Ole
    Commented Mar 10, 2016 at 10:50
  • 2
    I can't say I'm following why you would like to have {% content %} inside a component file like this. Site content is a global thing so I personally would have the content block in your main layout template, so you can then define the content for each page from the main layout. I'll leave my answer on and I'll see what other people come back with!
    – Jamie Wade
    Commented Mar 10, 2016 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.