1
votes

Please help me understand the right way to use template inheritance in twig.

I have a template base.html.twig that all my other templates extend. This contains the html, head, body, etc. tags and a few blocks.

I would like to move the < head > section from the base.html.twig template into its own file head.html.twig. If I use the include directive then the title block in that section no longer gets overridden properly by the extending templates.

I determined that I could work around this by setting the title as a variable in the extending template and passing it in my include statement. But now I have pages that need extra bits of javascript loaded in the < head > section, so I have to add variables to indicate which of those to load...

Obviously this is a horrible kludge. What is the right way to do this?

EDIT: At the suggestion of @goto I tried replacing include with embed. Now my code looks like:

{# base.html.twig #}
<!DOCTYPE html>
<html>
{% embed 'AppBundle::head.html.twig' %}
    {% block title %}My Company Name{% endblock %}
{% endembed %}
<body>
    {% block content %}{% endblock %}
</body>
</html>

{# head.html.twig #}
<head>
    <title>{% block title %}{% endblock %}</title>
    <!-- load other css, js, etc -->
</head>

{# page.html.twig #}
{% extends 'AppBundle::base.html.twig' %}
{% block title %}{{ page.title }} - My Company Name{% endblock %}
{% block content %}
    <h1>{{ page.title }}</h1>
    {{ page.content|raw }}
{% endblock %}

But this doesnt work, the title is always "My Company Name".

3

3 Answers

1
votes

Found the solution. I needed the "use" tag:

{# base.html.twig #}
<!DOCTYPE html>
<html>
{% use 'AppBundle::head.html.twig' %}
{% block head %}
    {{ parent() }}
{% endblock %}
<body>
    {% block content %}{% endblock %}
</body>
</html>

{# head.html.twig #}
{% block head %}
    <head>
        <title>{% block title %}My Company Name{% endblock %}</title>
        <!-- load other css, js, etc -->
    </head>
{% endblock %}

{# page.html.twig #}
{% extends 'AppBundle::base.html.twig' %}
{% block title %}{{ page.title }} - My Company Name{% endblock %}
{% block content %}
    <h1>{{ page.title }}</h1>
    {{ page.content|raw }}
{% endblock %}
0
votes

Okay, for example you have a base.html.twig

<html>
<head>
    <title>{% block title %}{% endblock %}</title>

    <link rel="shortcut icon" href="{{ Someurl }}">

    {% block css %}
     ..... ///some css here
    {% endblock %}

    {% block js %}
    ...//javascript goes here
    {% endblock %}
    .......

With twig inheritance you can ovverride any of these blocks in your child like this:

child.html.twig

{% extends ::base.html.twig %}
{% block js %}
    {{ parent() }}
   .... your new js
{% endblock %}

With key word {{ parent() }} you will include existing data from base template to your current one, without it you will get clear block.

0
votes

Try embed instead of include, it allows you to redefine internal blocks of the included part:

{% embed "YourBundle:Acme:_embedded.html.twig" %}
    {% block header%}
        A new header
    {% endblock header%}
    {% block body%}
        A new body
    {% endblock body%}
{% endembed %}

See the the doc for more information