Even though this question is old, I want to clarify a few things, since there is no real answer provided.
The underlying problem here is that block
is evaluated during compile time, while if
is evaluated during run-time. This means that blocks are always defined, one cannot define blocks conditionally. That is also the reason why blocks cannot have dynamic names.
With the template from the question, this is not a problem:
classes.html.twig:
{% if redirect == 'a' %}
{% block classA %}active{% endblock %}
{% elseif redirect == 'b' %}
{% block classB %}active{% endblock %}
{% elseif redirect == 'c' %}
{% block classC %}active{% endblock %}
{% else %}
{% block classD %}active{% endblock %}
{% endif %}
If we render this, we get 'active', i.e. the expected output. While each block is defined, only one of them is rendered, because of the if
. The problem is only revealed if we have inheritance. So let's say we have the following parent template (I assume something like that was used by the poster):
parent.html.twig:
{% block classA %}{% endblock %}
{% block classB %}{% endblock %}
{% block classC %}{% endblock %}
{% block classD %}{% endblock %}
And change our extending template to extend this (also added classE for demonstration purposes):
classes.html.twig:
{% extends "parent.html.twig" %}
{% if redirect == 'a' %}
{% block classA %}active{% endblock %}
{% elseif redirect == 'b' %}
{% block classB %}active{% endblock %}
{% elseif redirect == 'c' %}
{% block classC %}active{% endblock %}
{% else %}
{% block classD %}active{% endblock %}
{% endif %}
{% block classE %}undefined{% endblock %}
Now, if we render classes.html.twig, we get 'activeactiveactiveactive'. As before, the blocks are all defined with 'active', but the parent template has no conditional rendering, so all of them are shown. Block 'classE' is not rendered, because it is not defined in the parent template.
To fix this, one needs to essentially swap the if
and block
statements.
{% extends "parent.html.twig" %}
{% block classA %}
{% if redirect == 'a' %}
active
{% endif %}
{% endblock %}
{% block classB %}
{% if redirect != 'a' and redirect == 'b' %}
active
{% endif %}
{% endblock %}
{% block classC %}
{% if redirect != 'a' and redirect != 'b' and redirect == 'c' %}
active
{% endif %}
{% endblock %}
{% block classD %}
{% if redirect != 'a' and redirect != 'b' and redirect != 'c' %}
active
{% endif %}
{% endblock %}
Sadly, we lose the if/else structure when we do this, so we have to write more conditions. To fix this, we can add an intermediate step using a variable.
{% extends "classes.html.twig" %}
{% if redirect == 'a' %}
{% set render = 'a' %}
{% elseif redirect == 'b' %}
{% set render = 'b' %}
{% elseif redirect == 'c' %}
{% set render = 'c' %}
{% else %}
{% set render = 'd' %}
{% endif %}
{% block classA %}
{% if render == 'a' %}
active
{% endif %}
{% endblock %}
{% block classB %}
{% if render == 'b' %}
active
{% endif %}
{% endblock %}
{% block classC %}
{% if render == 'c' %}
active
{% endif %}
{% endblock %}
{% block classD %}
{% if render == 'd' %}
active
{% endif %}
{% endblock %}