Menü bağlantısı kardeşlerini edinin


11

Sadece geçerli sayfanın bağlantıları kardeş olan Drupal 8'de bir menü oluşturmaya çalışıyorum. Yani menü:

  • Ev
  • Ebeveyn 1
    • Alt ebeveyn 1
      • Çocuk 1
    • Alt ebeveyn 2
      • Çocuk 2
      • Çocuk 3
      • Çocuk 4
  • Ebeveyn 2

"Çocuk 3" sayfasında olduğumda, bağlantı kurmak için bir menü bloğunun şöyle görünmesini istiyorum:

  • Çocuk 2
  • Çocuk 3
  • Çocuk 4

Sanırım bunu D7'de nasıl yapacağımı biliyorum, ama bu bilgiyi D8'e çevirmekte zorlanıyorum. Bu, D8'de yapılabilecek bir şey mi? Ve eğer öyleyse, birileri beni nasıl yapacağımı doğru yönde gösterebilir mi?

Teşekkürler!

Açıklama: Farklı derinliğe sahip menü öğelerinin kardeşlerini görüntüleyebilmesi için alt düzey değişken olmalıdır. Yani, örneğin, çocuklar için bir menü istemenin yanı sıra, alt ebeveynler için bir menüye ve ebeveynler için bir menüye ihtiyacım var. Ayrıca menünün ne kadar derine gittiğini ve tüm bölümlerde bu kadar derin olup olmadığını kontrol edemiyorum.

Yanıtlar:


19

Böylece, özel bir blok oluşturarak ve yapı yönteminde, kendisine eklenmiş transformatörlerle menü çıktısı vererek bunu yapmama izin verecek bazı kodları bulmaya başladım. Bu, bloğun içindeki menüyü nasıl alacağımı ve ona transformatörleri nasıl ekleyeceğimi anlamak için kullandığım bağlantı: http://alexrayu.com/blog/drupal-8-display-submenu-block . Benim build()böyle görünüyordu:

$menu_tree = \Drupal::menuTree();
$menu_name = 'main';

// Build the typical default set of menu tree parameters.
$parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);

// Load the tree based on this set of parameters.
$tree = $menu_tree->load($menu_name, $parameters);

// Transform the tree using the manipulators you want.
$manipulators = array(
  // Only show links that are accessible for the current user.
  array('callable' => 'menu.default_tree_manipulators:checkAccess'),
  // Use the default sorting of menu links.
  array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
  // Remove all links outside of siblings and active trail
  array('callable' => 'intranet.menu_transformers:removeInactiveTrail'),
);
$tree = $menu_tree->transform($tree, $manipulators);

// Finally, build a renderable array from the transformed tree.
$menu = $menu_tree->build($tree);

return array(
  '#markup' => \Drupal::service('renderer')->render($menu),
  '#cache' => array(
    'contexts' => array('url.path'),
  ),
);

Transformatör bir hizmettir, bu yüzden intranet.services.ymlintranet modülüme bir tanımlama ekledim . Sınıfın üç yöntemi vardı: kullanıcının şu anda bulunduğu sayfanın üst öğesini almak için removeInactiveTrail()çağrılan ve menüyü yalnızca geçerli menü öğesinin alt öğelerine ve kardeşlerine (yani: etkin izde t).getCurrentParent()stripChildren()

Şöyle görünüyordu:

/**
 * Removes all link trails that are not siblings to the active trail.
 *
 * For a menu such as:
 * Parent 1
 *  - Child 1
 *  -- Child 2
 *  -- Child 3
 *  -- Child 4
 *  - Child 5
 * Parent 2
 *  - Child 6
 * with current page being Child 3, Parent 2, Child 6, and Child 5 would be
 * removed.
 *
 * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
 *   The menu link tree to manipulate.
 *
 * @return \Drupal\Core\Menu\MenuLinkTreeElement[]
 *   The manipulated menu link tree.
 */
public function removeInactiveTrail(array $tree) {
  // Get the current item's parent ID
  $current_item_parent = IntranetMenuTransformers::getCurrentParent($tree);

  // Tree becomes the current item parent's children if the current item
  // parent is not empty. Otherwise, it's already the "parent's" children
  // since they are all top level links.
  if (!empty($current_item_parent)) {
    $tree = $current_item_parent->subtree;
  }

  // Strip children from everything but the current item, and strip children
  // from the current item's children.
  $tree = IntranetMenuTransformers::stripChildren($tree);

  // Return the tree.
  return $tree;
}

/**
 * Get the parent of the current active menu link, or return NULL if the
 * current active menu link is a top-level link.
 *
 * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
 *   The tree to pull the parent link out of.
 * @param \Drupal\Core\Menu\MenuLinkTreeElement|null $prev_parent
 *   The previous parent's parent, or NULL if no previous parent exists.
 * @param \Drupal\Core\Menu\MenuLinkTreeElement|null $parent
 *   The parent of the current active link, or NULL if not parent exists.
 *
 * @return \Drupal\Core\Menu\MenuLinkTreeElement|null
 *   The parent of the current active menu link, or NULL if no parent exists.
 */
private function getCurrentParent($tree, $prev_parent = NULL, $parent = NULL) {
  // Get active item
  foreach ($tree as $leaf) {
    if ($leaf->inActiveTrail) {
      $active_item = $leaf;
      break;
    }
  }

  // If the active item is set and has children
  if (!empty($active_item) && !empty($active_item->subtree)) {
    // run getCurrentParent with the parent ID as the $active_item ID.
    return IntranetMenuTransformers::getCurrentParent($active_item->subtree, $parent, $active_item);
  }

  // If the active item is not set, we know there was no active item on this
  // level therefore the active item parent is the previous level's parent
  if (empty($active_item)) {
    return $prev_parent;
  }

  // Otherwise, the current active item has no children to check, so it is
  // the bottommost and its parent is the correct parent.
  return $parent;
}


/**
 * Remove the children from all MenuLinkTreeElements that aren't active. If
 * it is active, remove its children's children.
 *
 * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
 *   The menu links to strip children from non-active leafs.
 *
 * @return \Drupal\Core\Menu\MenuLinkTreeElement[]
 *   A menu tree with no children of non-active leafs.
 */
private function stripChildren($tree) {
  // For each item in the tree, if the item isn't active, strip its children
  // and return the tree.
  foreach ($tree as &$leaf) {
    // Check if active and if has children
    if ($leaf->inActiveTrail && !empty($leaf->subtree)) {
      // Then recurse on the children.
      $leaf->subtree = IntranetMenuTransformers::stripChildren($leaf->subtree);
    }
    // Otherwise, if not the active menu
    elseif (!$leaf->inActiveTrail) {
      // Otherwise, it's not active, so we don't want to display any children
      // so strip them.
      $leaf->subtree = array();
    }
  }

  return $tree;
}

Bunu yapmanın en iyi yolu bu mu? Muhtemelen değil. Ancak en azından benzer bir şey yapması gereken insanlar için bir başlangıç ​​yeri sağlar.


Altbilginin yaptığı budur. Menu.tree hizmetini kullanmak için +1.
mradcliffe

2
Service.yml dosyasına hangi kodun yerleştirilmesi gerektiğini söyleyebilir misiniz? Bir sınıfı service.yml dosyasından nasıl işaret edebilirim?
siddiq

Ebeveynler menü bağlantısı nasıl hariç tutulur?
Permana

3

Drupal 8, temelde yerleşik olan Menü Bloğu işlevselliğine sahiptir, tek yapmanız gereken Block Ui'de yeni bir menü bloğu oluşturmak ve bunu yapılandırmaktır.

Bu şu şekilde olur:

  • Yeni bir blok yerleştirip blok oluşturmak istediğiniz menüyü seçin.
  • Blok konfigürasyonunda "Başlangıç ​​menü seviyesi" ni seçmelisiniz 3.
  • Menü öğelerini yalnızca üçüncü düzeyden yazdırmak istiyorsanız, "Görüntülenecek maksimum menü düzeyi sayısı" değerini 1 olarak ayarlamak isteyebilirsiniz.

Ne yazık ki, sayfanın hangi seviyede olacağından emin olamıyorum, bu yüzden bunun için bir menü bloğu oluşturamıyorum. Ayrıca, site yapısının ne olduğuna bağlı olarak değişken seviyelerde olması gerekebilir.
Erin McLaughlin

Drupal 8 için menu_block şu anda geçerli düğümü takip etmek için işlevsellik içermiyor, burada incelenen yamalar; drupal.org/node/2756675
Christian

Statik kullanım için Tamam. Ancak, "Her sayfaya bir blok yerleştirin ve şu anda hangi düzeyde olursanız olun geçerli sayfanın kardeşlerini gösterin" gibi dinamik kullanım için değil.
leymannx

3

Geçerli bağlantıda kök ayarlamak hile yapabilir:

$menu_tree = \Drupal::menuTree();
$menu_name = 'main';

$parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
$currentLinkId = reset($parameters->activeTrail);
$parameters->setRoot($currentLinkId);
$tree = $menu_tree->load($menu_name, $parameters);

// Transform the tree using the manipulators you want.
$manipulators = array(
  // Only show links that are accessible for the current user.
  array('callable' => 'menu.default_tree_manipulators:checkAccess'),
  // Use the default sorting of menu links.
  array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
);
$tree = $menu_tree->transform($tree, $manipulators);

Hayır, maalesef bu sadece çocukları gösteriyor. Ama kardeş değil. OP kardeş istiyor.
leymannx

3

Kardeşler Menü Bloğu

@Icubes cevap yardımıyla MenuLinkTreeInterface::getCurrentRouteMenuTreeParametersmevcut rotanın aktif menü izini alabiliriz. Üst menü öğemiz de var. Bunu MenuTreeParameters::setRootyeni bir ağaç oluşturmak için başlangıç ​​noktası olarak ayarlamak, size istenen kardeşler menüsünü verir.

// Enable url-wise caching.
$build = [
  '#cache' => [
    'contexts' => ['url'],
  ],
];

$menu_name = 'main';
$menu_tree = \Drupal::menuTree();

// This one will give us the active trail in *reverse order*.
// Our current active link always will be the first array element.
$parameters   = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
$active_trail = array_keys($parameters->activeTrail);

// But actually we need its parent.
// Except for <front>. Which has no parent.
$parent_link_id = isset($active_trail[1]) ? $active_trail[1] : $active_trail[0];

// Having the parent now we set it as starting point to build our custom
// tree.
$parameters->setRoot($parent_link_id);
$parameters->setMaxDepth(1);
$parameters->excludeRoot();
$tree = $menu_tree->load($menu_name, $parameters);

// Optional: Native sort and access checks.
$manipulators = [
  ['callable' => 'menu.default_tree_manipulators:checkNodeAccess'],
  ['callable' => 'menu.default_tree_manipulators:checkAccess'],
  ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
];
$tree = $menu_tree->transform($tree, $manipulators);

// Finally, build a renderable array.
$menu = $menu_tree->build($tree);

$build['#markup'] = \Drupal::service('renderer')->render($menu);

return $build;

Bu çözüm bir cazibe gibi çalıştı. :)
Pankaj Sachdeva
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.