Drupal 8 Dynamic Dependent Views Exposed Filter Dropdowns

Drupal 8 Dynamic Dependent Views Exposed Filter Dropdowns

I recently needed to make a Drupal-8 view with the exposed filters filtered by the existing filters so there are no zero results pages available.

Here's the PHP for that, you'll also need to target your filter form and add an on change event to submit the filter form else you can still get the no result pages.

My view is a view of content teaser with 3 referenced vocabs on the content type.

Firstly I duplicated the entire view and called it the same as the first on with "Count" on the end and changed it to have no limit to the number of results returned and also to just return fields and only the title field.

This was because without it I wasn't getting the full list of terms I could filter by

All the things in CAPS are as descriptive as I could make them in 5 mins, you'll need to change them as required for your solution

<?php
 
/**
 * Implements hook_views_exposed_form_alter().
 *
 * Alters exposed filter for equipment selector to limit filtered results in a
 * new view
 */
function MYMODULE_form_views_exposed_form_alter(&$form, &$form_state) {
  if ($form['#id'] == 'views-exposed-form-VIEWID-page-1') {
    // Get whatever values selected by user in all menus
    $input = &$form_state->getUserInput();
 
    $args = [];
    foreach ($input as $arg) {
      if (!empty($arg)) {
        $args[] = $arg;
      }
    }
 
    $filters = ['FILTER_1', 'FILTER_2', 'FILTER_2'];
    foreach ($filters as $filter) {
      $form[$filter]['#options'] = MYMODULE_get_associative_array_from_view(
        'VIEWID_count', // viewi id
        'page_1', // view dsplay id
        $args, $filter
      );
    }
  }
}
 
/**
 * Filters out the unavailable options from the drop downs
 */
function MYMODULE_get_associative_array_from_view($view_id, $display_id, $args, $menu_chosen) {
 
  $options_array = array();
  $options_array['All'] = t('- Any -');
  $result = MYMODULE_get_view_result($view_id, $display_id, $args);
 
  foreach ($result as $row) {
    switch ($menu_chosen) {
 
      // views_get_view_result returns rows with original field name so don't
      // use filter identifier name to acceess, use field name
      case 'FILTER_1':
        $field = $row->_entity->get('FIELD_1')->getValue();
        break;
 
      case 'FILTER_2':
        $field = $row->_entity->get('FIELD_2')->getValue();
        break;
 
      case 'FILTER_2':
        $field = $row->_entity->get('FIELD_3')->getValue();
        break;
 
      default:
        break;
    }
 
    $target_id = $field[0]['target_id'];
    $term = MYMODULE_get_referenced_term($target_id);
    if (!empty($term)) {
      $term_name = $term->getName();
      $term_id = $term->id();
      if (!in_array($term_name, $options_array)) {
        $options_array[$term_id] = $term_name;
      }
    }
  }
 
  asort($options_array);
 
  return $options_array;
}
 
/**
 * Returns a term if in scope
 *
 * @param int $tid
 *
 * @return object
 */
function MYMODULE_get_referenced_term($tid = 0) {
  if (empty($tid)) {
    return;
  }
 
  $term = taxonomy_term_load($tid);
 
  if (empty($term)) {
    return;
  }
 
  return $term;
}
 
/**
 * Get the view result filtered by the arguments passed
 *
 * @param string $viewname
 * @param string $display
 * @param array $args
 *
 * @return boolean|array
 */
function MYMODULE_get_view_result($viewname, $display, $args) {
  // Get the view
  $view = \Drupal\views\Views::getView($viewname);
 
  if (!$view) {
    // The view could not be loaded. Add a watchdog message and leave the function
    \Drupal::logger('MYMODULE')->error('View @view not found', array('@view' => $viewname));
    return false;
  }
 
  // set the display machine name
  $view->setDisplay($display);
 
  // Set arguments for exposed filters
  // Note that you always need to use an array.
  // The arguments are passed in the order as they appear on the view
  $view->setArguments($args);
 
  // Execute the view
  // This function does not do any access checks on the view. It is the
  // responsibility of the caller to check $view->access()
  $view->preview();
 
  if (!empty($view->result)) {
    return $view->result;
  }
}

More about this on the stack exchange thread here.

Comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.