4

I have an exposed filter for tags on my view. I want this filter to only show show used tags. I found some drupal 7 options like this one and the Views Selective Filter but can't seem to find a good drupal 8 option.

Can anyone help me out with a solution for this?

1
  • in the same way that is made in the article you can alter the form and just show the terms that you need. Nov 9, 2017 at 13:26

4 Answers 4

3

As Adrian said it was possible to change the code in the article a bit to make it suitable for Drupal 8. Here is my solution:

function MODULENAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  //id of the form you want to alter
  $formId = 'views-exposed-form-agenda-page-1';
  //field tags
  $select_field = 'field_tags_target_id';

  /**
   * Apply the form_alter to a specific form #id
   * the form #id can be found through inspecting the markup
   */
  if ($form['#id'] == $formId) {
    $available_terms = _get_available_terms();
    if (isset($available_terms)) { // Unset the existing list and add new one with available terms.
      unset($form[$select_field]['#options']);

      if ($form[$select_field]['#options']['All']) {
        $form[$select_field]['#options']['All'] = '- Any Term -';
      }

      foreach ($available_terms as $available_term) {
        $tid = $available_term[0];
        $name = $available_term[1];
        $form[$select_field]['#options'][$tid] = $name;
      }
    }
    else { // Unset all options except '- Any -'
      unset($form[$select_field]['#options']);
      $form[$select_field]['#options']['All'] = '- Any Term -';
    }
  }
}

function _get_available_terms() {
  //table name of tags field
  $node_tags_table = 'node__field_tags';

  $db = \Drupal::database();
  $query = $db->select($node_tags_table, 'nft');
  $query->distinct();
  $query->join('taxonomy_term_field_data', 'tname', 'tname.tid = nft.field_tags_target_id');
  $query->fields('nft', ['field_tags_target_id']);
  $query->fields('tname', ['name']);
  $result = $query->execute();

  $term_list = [];
  while ($row = $result->fetchAssoc()) {
    array_push($term_list, [$row['field_tags_target_id'], $row['name']]);
  }

  return $term_list;
}
2

In Drupal 8, I was able to display only tags with results with the following code. Note that I'm using Better Exposed Filters contrib module, and display my filter as a Select.

function mymodule_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form['#id'] == 'views-exposed-form-your-view-name-page') {

    if (array_key_exists('field_activities_target_id', $form)) {
      // Rewrite the default 'All' option
      if (!empty($form['field_activities_target_id']['#options']['All'])) {
        $option_default = ['All' => t('Choose a category')];
      }

      $options = $form['field_activities_target_id']['#options'];

      $connection = Database::getConnection();
      $query = $connection->select('node__field_activities', 'activities');
      $query->join('node_field_data', 'n', 'n.nid = activities.entity_id');
      $query->fields('activities', ['field_activities_target_id']);
      $query->fields('n', ['status']);
      $query->condition('activities.bundle', 'your_node_type_name');
      $query->condition('n.status', 1);
      $data = $query->distinct()->execute();

      $results = array_flip($data->fetchAll(\PDO::FETCH_COLUMN, 'field_activities_target_id'));
      $options = array_intersect_key($options, $results);

      // Rebuild the option select
      $form['field_activities_target_id']['#options'] = $option_default + $options;
    }
  }
}

This article was a great help : https://johndevman.com/only-show-options-in-a-views-exposed-filter-that-belong-to-result-set/

2

Here is the D8 module I am using to accomplish this function: https://www.drupal.org/project/selective_better_exposed_filters

It depends on better_exposed_filters. https://www.drupal.org/project/better_exposed_filters

It's still in beta, so test locally in your environment first, but it worked well in my testing. It won't create the (selective) filter options when you add filter criteria like you are used to in the old D7 module, but it accomplishes the same function:

Once you have an exposed filter in filter criteria, go to "exposed form style" under advanced then switch to better exposed filters (selective). Click apply

enter image description here

And then to enable it, check the box "show only used terms" down towards the bottom. Click apply.

enter image description here

Edit: If you have multiple exposed filters, you can set them each individually under each "more options for..." or you can set all of them globally at the very bottom of the settings options.

Pretty simple for those of us who aren't comfortable writing our own modules.

1
  • Thank you Tony! This module should be more known May 28, 2021 at 10:33
0

The selective better expose filters seems like an ideal solution yet after installing the module I do not get an option 'show only used terms'?

enter image description here

1
  • 1
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Sep 2, 2022 at 15:29

Your Answer

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

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