Drupal - Show only used taxonomy terms in exposed filters
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;
}
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/