Hello all,

So I am new to Drupal and now trying to find my way in Drupal 8. I have problem with displaying my HTML based on if certain blocks are available.

I have the following code, showing a sidebar and content region. The sidebar is being filled with 'widgets' and 'subnavigation' based on the node.

 {% if page.left_sidebar %}
<div class="col-md-3">
    {{page.left_sidebar}}
</div>
{% endif %}

<div class="col-md-9">
    {{ page.content }}          
</div>

When there is no subnavigation or widgets, the page.left_sidebar wrapping div is still being printed. Checking the 'page.left_sidebar' with kint shows me that the left_sidebar indeed has a widgets and a subnavigation block, but only with a #cache, #weight integer and #lazy_builder array. Even on pages with subnavigation or sidebar is is like this. I would like to have something like below so my class col-md-3 is not being printed. Hope somebody can point me in the right direction.

 {% if subnavigation or widgets %}
<div class="col-md-3">
    {{page.left_sidebar}}
</div>
{% endif %}

<div class="col-md-9">
    {{ page.content }}          
</div>

Best regards,
MSN

Comments

Shashwat Purav’s picture

Michiel Snijder’s picture

Hi Shashwat, thanks for you quick reply. I found the same pages but thought this was something different as comments on that thread started already over 5 years ago. Do you perhaps know any workaround for the problem? Checking if there is content in the div using JS or CSS is terrible. If I there is no sidebar, the sidebar 3-col div should go away, and the content div should be 3 cols wider. I thought this would be easy by just using and if else construction with twig :(

Artnetik’s picture

I have the same problem right now. Using the Basic base theme, displaying sidebar even if it's empty is super annoying. Did anyone found a solution to this bug?

SimiS’s picture

This worked for me (although not in all cases!).

In page.html.twig:

{% if page.content is defined and page.content|render|striptags|trim  %}
    <div class="main-content">
       {{ page.content }}
    </div>
{% endif %}
Artnetik’s picture

Looks like my case is special : ) But good to know this solution! Will test for other projects.

ressa’s picture

Thanks for sharing @SimiS! I used your suggestion to fix the empty region problem in the Bootstrap theme.

SimiS’s picture

Great!
But make sure you test it good, because in some cases it didn't display some blocks that were in the region and should be displayed.

hkirsman’s picture

@SimiS, this does not work with blocks because the content might not be html but this placeholder (see below). It worked with main language but not in 2 other languages.
<drupal-render-placeholder callback="Drupal\block\BlockViewBuilder::lazyBuilder" arguments="0=eventregistrationform&amp;1=full&amp;2" token="afb5cea2"></drupal-render-placeholder>
I learned the hard way - day of debugging.

MrTucker’s picture

Thanks, this led me to a working solution, posted below.

MrTucker’s picture

Test for empty content in a preprocess_html function, and add classes to the page conditionally.

function yourtheme_preprocess_html(&$variables) {
  // Add information about the number of sidebars.
  $has_primary_sidebar = !empty(trim(strip_tags(render($variables['page']['sidebar_primary']))));
  $has_secondary_sidebar = !empty(trim(strip_tags(render($variables['page']['sidebar_secondary']))));

  if ($has_primary_sidebar && $has_secondary_sidebar) {
    $variables['attributes']['class'][] = 'layout-two-sidebars';
  }
  elseif ($has_primary_sidebar) {
    $variables['attributes']['class'][] = 'layout-one-sidebar';
    $variables['attributes']['class'][] = 'layout-sidebar-primary';
  }
  elseif ($has_secondary_sidebar) {
    $variables['attributes']['class'][] = 'layout-one-sidebar';
    $variables['attributes']['class'][] = 'layout-sidebar-secondary';
  }
  else {
    $variables['attributes']['class'][] = 'layout-no-sidebars';
  }
}
jwilson3’s picture

Cross-post from my comment here, but worth repeating: if you chose to go the route of either strip_tags php function in preprocess or |striptags Twig filter, be very careful in which regions you use it and watch out for false positives. For example, the highlighted region could easily contain only media elements wrapped up inside HTML tags <img> <object> <iframe> etc that would be incorrectly filtered.

In my own implementation for a contrib theme, I've purposefully left out |striptags Twig filter to prevent these false positives.

This does have one unfortunate drawback, that when twig_debug is enabled, the regions show up even if technically empty due to the auto-generated <!-- theme suggestions -->.  I haven't found a foolproof way to strip these HTML comments, and figured I'd better not bother. 

JFKiwad’s picture

Instead of rendering with render(), i suggest to use the service like so

$rendered_sidebar_primary = \Drupal::service('renderer')->renderRoot($variables['page']['sidebar_primary']);
$has_primary_sidebar = !empty(trim(strip_tags($rendered_sidebar_primary)));

your version still output <drupal-render-placeholder>
Maybe this worked on older version, but not on 8.5+.

Thanks

AlexeiK’s picture

Hi!

In a project, I needed to check if a block in region will render out the an image. The block was constructed in a view, so even if the output was empty, the block had mark-up, thus not empty!

As my block had only one image in it I used:

  {% if 'img' in page.hero|render|trim %}
    {{ page.hero }}
  {% else %}

Hope this helps someone

charlie59’s picture

Many years later, maybe this will help someone.
if (empty($variables['page']['sidebar'])) {

//do something

}

hassebasse’s picture

Hi charlie59

I'm not good in code at all so I can't figure out what to do with that code. In place of //do something what shall I write to give the page full width if I have an empty block on left side in the theme? And where to put your code??

charlie59’s picture

It's a bit complicated to explain, but if the sidebar is a region you could unset it, so it did not appear. Or you could load a css library to hide or minimize the sidebar.

I set a variable that I then used as a class in the Twig template to hide the sidebar.

$variables['contentAreaClass'] = 'no-sidebar';
Anybody’s picture

Until this will hopefully be solved in core one day, there is now a workaround module at https://www.drupal.org/project/twig_real_content

Please help to test and improve it and provide feedback in issues. :)

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes