2

I have a layout template:

{% set bodyClass = [] %}

<body class="{% for class in bodyClass %}{{ class }} {% endfor %}">
    {{ block('pageBody') }}
</body>

And a template that extends it:

{% extends 'layout' %}

{% set bodyClass = bodyClass|merge(['myclass']) %}

{% block pageBody %}
    <h1>Hello World</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, consequuntur!</p>
{% endblock %}

When I try to append to the bodyClass variable I get the error:

Variable "bodyClass" does not exist.

However if I call the variable:

{% for class in bodyClass %}
  {{ class  }}
{% endfor %}

The template renders fine. Why can't I merge onto a variable that's been set in an extended template? Is there another way to do this?

1

2 Answers 2

4

You can only access the parent's variable, not modify it. You could however simply add another block specifically for the body class, like so:

Layout template:

<body class="{% block body_class %}default-class-1 default-class-2{% endblock %}">
    {{ block('pageBody') }}
</body>

Template that extends it:

{% extends 'layout' %}

{% block body_class %}{{ parent() }} myclass{% endblock %}

{% block pageBody %}
    <h1>Hello World</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, consequuntur!</p>
{% endblock %}

Note the call to parent() that includes the default classes defined in the parent template.

1
  • Thanks. Not 100% ideal since I won't be able to control the spacing before and after the classes, but I guess it's good enough.
    – kmgdev
    Commented Dec 18, 2018 at 4:24
0

I often just declare a second (optional) variable in each template, with the default classes set in a layout, and merged with any additional ones:

{# __layout/base.twig #}

{% set defaultBodyClasses = ['app'] %}
{# Use `default([])` to make this a non-mandatory assignment in your templates: #}
{% set bodyClasses = templateProvidedBodyClasses | default([]) | merge(defaultBodyClasses) %}

<body class="{{ bodyClasses | join(' ') }}">...</body>

…and then in a template, say rendering an Entry…

{# _pages/page.twig #}

{% extends '__layouts/base' %}

{% set templateProvidedBodyClasses = [
    'app--my-static-flag',
    "app--section-#{entry.section.handle}",
    "app--type-#{entry.type.handle}"
] %}

Hope this helps illuminate another option!

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.