I'm trying to limit terms in a view facet (exposed filter) based on a contextual filter.

I have products with a 'category/type' taxonomy term. The terms are 2-level, looking roughly like this:

  • Category 1
    • Type a
    • Type b
    • Type c
  • Category 2
    • Type d
    • Type e
    • Type f

We can assign multiple terms from the 2nd level to each product.

I have a view that shows only products within a 1st level category (e.g. Category 1) by contextual filter, and then allow the user further filter by 'Type' from a facet (should show 'Type a', 'Type b', 'Type c' when contextual filter is 'Category 1').

The problem is that, since we can assign terms from multiple categories to the same product, we are seeing types from 'Category 2' in the facets, despite the fact that we're filtering by 'Category 1'.

Is there a hook to alter the facets, based on the contextual filter applied to the view?

So far, I got as far as eliminating an option from an exposed filter:

use \Drupal\Core\Form\FormStateInterface;
 * Implements hook_form_views_exposed_form_alter().
function cd_general_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $view_ids = [
  if ($form_id == 'views_exposed_form' && in_array($form_state->get('view')->id(), $view_ids)) {

To test, I duplicated my view so that I have one with normal exposed filters, and the original with facets related to those filters. The code above works on the exposed filters, but not on my facets.

My next step is to look again for hooks in the facets and core_views_facets modules.

1 Answer 1


I was able to use hook_preprocess_facets_item_list.

 * Implements hook_preprocess_facets_item_list().
function mymodule_preprocess_facets_item_list(&$variables) {
  $facet_id = $variables['facet']->id();

  if ($facet_id === 'content_category') {
    // In the product categories by material view, remove category
    // facets based on the contextual parent category.
    $path = \Drupal::service('path.current')->getPath();
    $contextual_category_name = explode('/', $path)[2];
    $contextual_category_term = \Drupal::entityTypeManager()
        'name' => $contextual_category_name,
        'vid' => 'product_category',
    // First array element, only.
    $contextual_category_term = reset($contextual_category_term);
    foreach ($variables['items'] as $key_item => $item) {
      $tid = $item['#attributes']['data-drupal-facet-item-value'];
      $term = Term::load($tid);
      $parent = \Drupal::entityTypeManager()
      // First array element only.
      $parent = reset($parent);
      $parent_id = $parent->id();
      if ($parent_id !== $contextual_category_term->id()) {
        // Remove facets not within the current parent category.

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.