2

I need to set a body class if a facet filter is active.

It should be done in yourtheme_preprocess_html

if Facet is active
then
$variables['attributes']['class'][] = 'facet-active';

for fulltext search terms it works like that

  $variables['attributes']['class'][] = 'search-' . \Drupal::request()->query->get('search_api_fulltext');

Anyone know how to dig out the information if a facet is active or not.

thanks in advance

Matthias

1 Answer 1

2

You don't know when the HTML template is rendered whether a facet is active or not. So in mytheme_preprocess_html() assume it is not:

$variables['attributes']['class'][] = 'facet-is-not-active-class';

In the facets block replace the placeholder class if the block is visible:

function mytheme_preprocess_block(&$variables) {
  if ($variables['configuration']['provider'] == 'facets') {
    if (!in_array('hidden', (array) $variables['attributes']['class'])) {
      $variables['#attached']['placeholders']['facet-is-not-active-class'] = [
        '#markup' => 'facet-active',
      ];
    }
  }
}

Important is that the placeholder string facet-is-not-active-class is unique, use a longer name or even a hash. Placeholders are replaced for all occurrences of the string on the page.

Issue with nested placeholders

This works only for blocks not auto-placeholdered. The facet block, unfortunately, is always placeholdered. It sets cache max-age 0 which meets the default condition for auto-placeholdering. See https://www.drupal.org/docs/drupal-apis/render-api/auto-placeholdering#s-what

To prevent that you can set #create_placeholder to FALSE:

/**
 * Implements hook_block_build_BASE_BLOCK_ID_alter().
 */
function mymodule_block_build_facet_block_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
  $build['#create_placeholder'] = FALSE;
}

Caveat: This is a real performance killer, it doubles the page loading times in my tests. So if performance is important you probably should look for a client-side solution, better CSS or a javascript library which adds the necessary classes.

6
  • I didn't know of that special $variables['#attached']['placeholders'] before. Is there some sort of documentation for all the possibilities inside the #attached array? I know of drupalSettings, libraries and html_head keys in there, but there seems to be so much more.
    – Hudri
    Commented Apr 4, 2022 at 10:05
  • Regarding the magic keys in $variables['#attached']: googled myself from this blog to the API docs. Important: Read beyond the docs in the header and look at the (un-)supported keys in code
    – Hudri
    Commented Apr 4, 2022 at 10:20
  • That is a fantastic approach. Thanks a lot. But I cant get it to work and dont know why not. The facet-is-not-active-class is defined in a preprocess_html hook before the preprocess_block hook. facet-is-not-active-class shows up in the body class, but is not replaced after using a facet filter.
    – Matthias
    Commented Apr 4, 2022 at 12:03
  • must have to do with one of the two if clauses if ($variables['configuration']['provider'] == 'myblockid') { if (!in_array('hidden', (array) $variables['attributes']['class'])) { even if i test it with other blocks which are visible all the time it doesnt replace the initial facet-is-not-active-class bodyclass.
    – Matthias
    Commented Apr 4, 2022 at 12:32
  • I've tested some blocks, too. Some work, others not. It seems like blocks which are placeholdered themselves can only placeholder within the block. Unfortunately the facet block is always placeholdered because it sets cache max-age 0. I delete the answer after a while if no solution comes up. As an alternative to this, you could attach a javascript library to the block to check the visibility of the facets client-side.
    – 4uk4
    Commented Apr 4, 2022 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.