3

I have a twig template with the following block:

{% block dashboard %}
    {% include "::user_dashboard.html.twig" %}
{% endblock dashboard %}

Later in that template, I want to set a class on a div based on whether or not there is anything in that block (i.e., by default, it will have the include above, but children of this template may override it and empty it out).

What I had (that somewhat worked) was ...

{% set _dashboard = block('dashboard') %}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">

The problem here is that whole dashboard block gets called twice. This wouldn't bother me too much except that block renders a few controller actions, i.e. ...

{% render "UserWidget:userAppMenu" %}

... and the code in that action is being called twice. For various reasons, not the least of which is performance, this messes with some of the stuff in that dashboard block.

So, my question is ... is there any way to tell if that block is empty without loading it twice? Is there something really simple I'm missing or is this even possible?

Thanks!

EDIT:

Here is my full template if it helps clarify things:

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

{% block layout %}

{% block header %}
    {% include "::header.html.twig" %}
{% endblock header %}

<div id="container" class="row-fluid">

    {% block dashboard %}
        {% include "::user_dashboard.html.twig" %}
    {% endblock dashboard %}

    {% set _dashboard = block('dashboard') %}
    {% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) %}  
    <div id="main" class="{{ _mainWidth }}">
        <h1 class="page-title">{% block page_title %}{% endblock %}</h1>
        {% block main_filters %}{% endblock %}

        {% if app.session.flashbag.has('message') %}
          <div class="alert alert-block alert-success">
            <ul>
                {% for flashMessage in app.session.flashbag.get('message') %}
                    <li>{{ flashMessage }}</li>
                {% endfor %}
            </ul>
          </div>
        {% endif %}

        {% if app.session.flashbag.has('warning') %}
          <div class="alert alert-block alert-success">
            <ul>
                {% for flashWarning in app.session.flashbag.get('warning') %}
                    <li>{{ flashWarning }}</li>
                {% endfor %}
            </ul>
          </div>
        {% endif %}

        {% block body %}{% endblock %}

        {% block footer %}
            {% include "::footer.html.twig" %}
        {% endblock footer %}
    </div>

</div>

{% endblock layout %}

Here you can see on lines 11 and 15 - both of those actually seem to include and process what is in that include.

Delford Chaffin
  • 623
  • 7
  • 23
  • There is no `render` tag in Twig... – Paul May 21 '13 at 20:52
  • 4
    @Paulpro There is! But the documentation is really..well...there is none. But see [this](http://stackoverflow.com/questions/16297393/twig-render-vs-include-when-and-where-to-use-one-or-the-other) great answer on stackoverflow. – SirDerpington May 21 '13 at 20:55
  • @SirDerpington Oh wow. Thanks! I never knew about that tag. – Paul May 21 '13 at 20:58
  • I'm using Symfony 2.1 and I'm not sure where I found that render syntax, but it works. Apparently, the new (2.2, 2.3) way is slightly different: http://symfony.com/doc/master/book/templating.html#embedding-controllers ... If I thought upgrading to 2.2 and that new syntax would help, I'd do that. I still may anyway, but I'm not convinced that is the only issue here. – Delford Chaffin May 21 '13 at 21:18

1 Answers1

0

What about this? This way the block should only be rendered once, when you call block('dashboard').

{# at top of twig #}
{% set _dashboard = block('dashboard') %}

{# where ever you include your block #}
<div>
    {{ _dashboard|raw }}
</div>

{# and your main #}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">
Emii Khaos
  • 9,983
  • 3
  • 34
  • 57
  • The problem here is I need to put something inside that block by default, so my template includes that default content. Later, when I set a variable to that block to test if it is now empty, that simple call {% set _dashboard = block('dashboard') %} actually includes the block again. I'll edit my question to include the full template in hopes that will help clarify ... – Delford Chaffin May 22 '13 at 14:42
  • For now, I've gone ahead and set up an additional template - one with and one without the dashboard. Then, instead of emptying that block where I don't need it, I'm extending the template that doesn't have it. This works pretty easily and will allow me to move on, but I still with there was a way to do it with the one template. – Delford Chaffin May 22 '13 at 15:46