Search code examples
drupaldrupal-8drupal-taxonomyhook-form-alter

Drupal 8: Taxonomy page limit exposed filter options based on parent term


In a Drupal 8 site, I have a taxonomy page with a view block on it. The view lists articles tagged with the term of the page you are on. It also shows articles tagged with the child terms of the current taxonomy page.

I am using the exposed filter "Content: Has taxonomy terms (with depth) (exposed)" to let a user filter the articles based on the child terms. Currently that filter shows all of the terms regardless of which taxonomy you are currently on.

Here is an example of the items listed in the exposed filter:

Mammals
 - Cat
 - Dog
Reptiles
 - Lizard
 - Snake
Amphibians
 - Frog
 - Salamander

The URL for one of the parent terms would be:

site.com/animal/mammals

I need to limit the list of options within the exposed filter to only show the children of the term based on the URL. So on the URL above, only Cat and Dog would be listed in the exposed filter.

In Drupal 7 I could accomplish this with a hook_form_alter in my theme.module using the URL arg(2) to get the term name. I cannot find any documentation on how to do this in Drupal 8.

Here is what I have found so far:

function myTheme_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-article-tags-block-1') {

    $term = arg(2);
    //Need D8 code to load term, find it's children and alter the select box to show those children

  }
}

I am open to other options if this is not the way to accomplish my goal. Thank you in advance.


Solution

  • hook_form_alter will still work, though arg() is removed in Drupal 8.

    It is not clear to me what the general replacement for arg() is. The code below uses two techniques to get the taxonomy term id.

    You probably want to turn caching off in the view during development.

    function myTheme_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
    
      if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-article-tags-block-1') {
    
        // initial page load
        $parameters = \Drupal::routeMatch()->getRawParameters();
        $this_term_id = $parameters->get('taxonomy_term');
    
        // ajax refresh via apply button
        if (!isset($this_term_id)) {
          $this_term_id = $_REQUEST['view_args'];
        }
    
        // get children of $this_term_id
        $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('tags', $parent = $this_term_id, $max_depth = NULL, $load_entities = FALSE);
    
        // get rid of all options except default
        $all_option = $form['term_node_tid_depth']['#options']['All'];
        unset($form['term_node_tid_depth']['#options']);
        $form['term_node_tid_depth']['#options']['All'] = $all_option;
    
        // add child terms
        foreach ($tree as $term) {
          $option = new stdClass();
          $option->option[$term->tid]=$term->name;
          $form['term_node_tid_depth']['#options'][] = $option;
        }
      } 
    
    }