10

I have condition for printing regions in my page template as is not empty, but it will always print empty regions no matter what. What is the proper way to detect empty regions?

For example, {% if page.local_tasks is not empty %}{{ page.local_tasks }}{% endif %} prints out <div class="region region-local-tasks"></div>.

If I render the region in themename_preprocess_page() with var_dump(drupal_render($variables['page']['highlighted'])); I will get SafeString with placeholder token:

<div class="region region-highlighted"><drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="a8c34b5e"></drupal-render-placeholder></div>

So, technically the region is not empty but I can do nothing about it.

closed as unclear what you're asking by kiamlaluno Aug 27 at 17:12

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • What does page.local_tasks contain when you feel it should be empty? – Clive Sep 23 '15 at 10:23
  • That's a region for local tasks block. – user21641 Sep 23 '15 at 10:54
  • Right, but what does the object contain? It's not empty, so look to see what other properties it has that might tip you off that there's no content (does it contain a string or an un-rendered array essentially?) – Clive Sep 23 '15 at 11:04
  • I have the same problem, and it seems this is a bug – Yusef Mohamadi Sep 18 '16 at 9:51
10

TL;DR for this is that there is no way to reliably check if region is empty or not in the template.

In Drupal 8 at the point when we are at the template level we are unable to tell whether the region has content or not because the content is rendered lazily. There is open Drupal 8 issue for this.

What you probably will have to do to achieve this is to write CSS that tests whether the region is empty. You can try using using :empty pseudo-selector.

  • I have concluded that the most reliable way to get around this problem is to add template suggestions in hook_theme_suggestions_HOOK_alter and remove the regions entirely from the template where its not supposed to be visible. – Johan Sep 18 '17 at 10:08
10

try to apply filters after render, like this :

{% set has_sidebar_first = page.sidebar_first|render|striptags|trim is not empty %}
{% if has_sidebar_first %}
    {# ... #}
{% endif %}
  • this worked for me – Andrew Kozoriz Jan 21 '18 at 20:37
  • This is quite useful. – ACanadianCoder Feb 8 '18 at 19:01
  • 1
    This approach doesn't work because it doesn't take into account that some regions might get rendered into placeholders, which then will be later replaced with the actual markup. There simply isn't any way to determine whether a region is empty or not in the html.html.twig file. If you want to read the full background of this problem, I suggest reading this Drupal Core issue – lauriii Jan 25 at 7:43
  • As @lauriii said, this does not work with drupal placeholders (my views in blocks typically get filtered out due to the strip_tags filter). – Dakwamine Mar 11 at 9:19
2

In twig you should really be able to do:

{% if page.local_tasks %}{{ page.local_tasks }}{% endif %}

However perhaps there is something within page.local_tasks (like empty markup). Please try the following:

{% if page.local_tasks|striptags|trim %}{{ page.local_tasks }}{% endif %}
  • That debug snippet does not show anything(ie, nothing to display, the variable is empty). – user21641 Sep 23 '15 at 11:42
  • When you say debug do you mean dump? What happens if you do {% if page.local_tasks %}Crazy magic{% endif %}? – Queenvictoria Sep 23 '15 at 11:45
  • Reading your question I see that page.local_tasks is not empty. It's full of HTML. I'll update my answer. – Queenvictoria Sep 23 '15 at 11:47
  • Doesn't your snippet render the content twice if there is content? Or if it is rendered it is cached and it has no impact on performance? Also I don't understand why I need to do any workarounds. This should be working out of the box in the core. @Berdir any comment on this? – user21641 Sep 25 '15 at 8:37
  • The trouble is that local tasks is not empty. As twig and drupal are both following MVC there is nothing telling twig that is empty (it's not empty). Either you can write a preprocessor which overrides what local tasks provides when empty, provides another value with a 'count' type property you can test against, or something like I suggest. Somewhere or other you are going to take a hit. I think the performance bump will be negligible. – Queenvictoria Sep 25 '15 at 23:09
1

This worked for me.

{% if page.sidebar_first|render|striptags %}
<aside id="sidebar-first" class="sidebar sidebar-first layout-sidebar-first" role="complementary">{{ page.sidebar_first }}</aside>
{% endif %}

Simple enough.

  • I'm not sure but that might be making your sidebar render twice (once for evaluation and the other time for display). – Jigarius Dec 11 '17 at 20:38
-1

You should use Renderer service instead of drupal_render() which is deprecated, so:

$output = \Drupal::service('renderer')->renderRoot($some_array)

This will avoid generating drupal-render-placeholder tag in the output.

Similar issue: How to replace drupal-render-placeholder manually?

-1

try this :

 {% if page.local_tasks|render|striptags|trim  is not empty %}
    {{ page.local_tasks }}
 {% endif %}
-1

This actually works in my case

{% if page.sidebar_second|render|striptags('<drupal-render-placeholder>')|trim|length > 0 %}

striptags accepts a string of tags to keep, so you can also add whatever contentless tags you expect to have, like <form><img> etc.

-1

The following does also work when twig debugging is enabled:

{% set sidebarLength = page.sidebar_first|render|trim|striptags|length %}
{% if sidebarLength > 1 %}
  {% set has_sidebar_first = page.sidebar_first %}
{% else %}
  {% set has_sidebar_first = null %}
{% endif %}
-3

To detect if region is empty or not code like this:

{% if page.local_tasks %}
   {{ page.local_tasks }}
{% endif %}

In above code it checks if local_tasks region is empty or not and if empty then it will not print that region

  • 1
    not worked, this is always true – Yusef Mohamadi Sep 18 '16 at 10:48
  • The lazy rendering of the blocks is the cause for this snippet not to work. Because the array is not empty, but rendering it returns nothing. – Renrhaf Jan 15 '18 at 21:35