7

I have been looking searching for a while and couldn't find anything related to Drupal 8. There are Modules like Taxonomy Menu but unfortunately not for Drupal 8 which works accordingly.

Is there already any solution to build-up a menu out of the taxonomy terms for Drupal 8 without an individual development (php etc.)?

Further, I have realized when I create a taxonomy term and create a reference from a content I don't get the overview of contents linked to the term.

Hope my point is clear.

  • There's nothing yet, no - D8 is still in beta don't forget – Clive Jun 16 '15 at 11:58
  • Taxonomy Menu now has a D8 release. – acrosman Mar 25 '16 at 13:31
  • @Clive the guys over at taxonomy_menu could use some good help! :) – Alex Jun 9 '16 at 17:03
5

I needed the same thing. Unfortunately there is nothing for it yet so I had to create something for time being. It is not pretty but it works so I don't care.

/**
 * Returns renderable array of taxonomy terms from Categories vocabulary in
 * hierarchical structure ready to be rendered as html list.
 *
 * @param int $parent
 *   The ID of the parent taxonomy term.
 *
 * @param int $max_depth
 *   The max depth up to which to look up children.
 *
 * @param string $route_name
 *   The name of the route to be used for link generation.
 *   Taxonomy term(ID) will be provided as route parameter.
 *
 * @return array
 */
function mymodule_categories_tree($parent = 0, $max_depth = NULL, $route_name = 'mymodule.category.view') {
  // Load terms
  $tree = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree('categories', $parent, $max_depth);

  // Make sure there are terms to work with.
  if (empty($tree)) {
    return [];
  }

  // Sort tree by depth so we can easily find out the deepest level
  uasort($tree, function($a, $b) {
    // Change objects to array
    return \Drupal\Component\Utility\SortArray::sortByKeyInt((array) $a, (array) $b, 'depth');
  });

  // Get the value of the deepest term
  $deepest = end($tree);
  $deepest = $deepest->depth;

  // Create a structured array
  $list = [
    $parent => [
      'items' => [],
      'depth' => -1
    ]
  ];
  foreach ($tree AS $term) {
    $list[$term->tid] = (array) $term;
  }

  // See if we're on a node page and if so open the menu
  // on the proper position.
  $node = \Drupal::request()->attributes->get('node');
  if ($node) {
    $categories = $node->get('categories')->getValue();
    // Go through each category to find out the least deep one.
    // That one will be the one we'll open.
    $open_category = $parent;
    foreach ($categories AS $target) {
      $tid = $target['target_id'];
      if ($list[$tid]['depth'] > $list[$open_category]['depth']) {
        $open_category = $tid;
      }
    }
  } else {
    // See if we're on a term page and set the corresponding item
    // as active so we don't have to rely on JS.
    $term = \Drupal::request()->attributes->get('taxonomy_term');
    if ($term) {
      $open_term = $term->id();
    }
  }

  for ($i = $deepest; $i >= 0; $i--) {
    foreach ($list AS $term) {
      if ($term['depth'] == $i) {
        $item = [
          '#type' => 'link',
          '#weight' => $term['weight'],
          '#title' => $term['name'],
          '#url' => Url::fromRoute($route_name, ['taxonomy_term' => $term['tid']]),
          '#options' => [
            'set_active_class' => TRUE
          ]
        ];
        // If we're on a node page and this category was chosen
        // as active, set the link's class.
        if (isset($open_category) && $open_category == $term['tid']) {
          $item['#attributes']['class'][] = 'active';
        }
        // If we're on term page, set the link's class to 'active'
        // and if this item is a parent, open it.
        if (isset($open_term) && $open_term == $term['tid']) {
          $item['#attributes']['class'][] = 'active';
          if (!empty($term['items'])) {
            $item['#wrapper_attributes']['class'][] = 'open';
          }
        }
        // If this item has children
        if (!empty($term['items'])) {
          $item['items'] = $term['items'];
          $item['#wrapper_attributes']['class'][] = 'parent';
          $item['#prefix'] = '<span></span>';
          // If any of the child items has 'active' class,
          // or is also a parent and has 'open' class
          // add the 'open' class to this wrapper too.
          foreach ($item['items'] AS $child) {
            if (
              isset($child['#attributes']['class']) && in_array('active', $child['#attributes']['class'])
              || isset($child['#wrapper_attributes']['class']) && in_array('open', $child['#wrapper_attributes']['class'])
            ) {
              $item['#wrapper_attributes']['class'][] = 'open';
              break;
            }
          }
        }
        foreach ($term['parents'] AS $pid) {
          $list[$pid]['items'][$term['tid']] = $item;
        }
        unset($list[$term['tid']]);
      }
    }
  }

  return [
    '#theme' => 'item_list',
    '#items' => $list[$parent]['items'],
    '#attributes' => [
      'class' => ['categories-tree']
    ],
    '#attached' => [
      'library' => [
        'mymodule/categories_tree'
      ]
    ]
  ];
}
  • Since, I need more modules which are not available in drupal 8 I have decided to go with drupal 7. – sam Jun 22 '15 at 7:48
1

I've created a VERY rough and full of bugs version of taxonomy_menu for setting an existing menu parent for the terms to be appended to. Also, you can define a max depth.

I hope someday someone will review this and make it all magical.

1

There is now a Drupal 8 version of Taxonomy Menu. You can compliment it with Taxonomy Term Reference Tree Widget to get your desired results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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