Skip to content

Instantly share code, notes, and snippets.

@levymetal
Last active November 27, 2023 04:17
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save levymetal/5547605 to your computer and use it in GitHub Desktop.
Save levymetal/5547605 to your computer and use it in GitHub Desktop.
Custom Wordpress function which uses a nav walker to display a list of child pages from a common parent, which can be called from either the parent page (displays children) or any of the child pages (displays siblings). Detailed instructions available on my blog post here: http://christianvarga.com/how-to-get-submenu-items-from-a-wordpress-menu-…
<?php
wp_nav_menu( array(
'menu' => 'Menu Name',
'sub_menu' => true,
'direct_parent' => true
) );
<?php
// add hook
add_filter( 'wp_nav_menu_objects', 'my_wp_nav_menu_objects_sub_menu', 10, 2 );
// filter_hook function to react on sub_menu flag
function my_wp_nav_menu_objects_sub_menu( $sorted_menu_items, $args ) {
if ( isset( $args->sub_menu ) ) {
$root_id = 0;
// find the current menu item
foreach ( $sorted_menu_items as $menu_item ) {
if ( $menu_item->current ) {
// set the root id based on whether the current menu item has a parent or not
$root_id = ( $menu_item->menu_item_parent ) ? $menu_item->menu_item_parent : $menu_item->ID;
break;
}
}
// find the top level parent
if ( ! isset( $args->direct_parent ) ) {
$prev_root_id = $root_id;
while ( $prev_root_id != 0 ) {
foreach ( $sorted_menu_items as $menu_item ) {
if ( $menu_item->ID == $prev_root_id ) {
$prev_root_id = $menu_item->menu_item_parent;
// don't set the root_id to 0 if we've reached the top of the menu
if ( $prev_root_id != 0 ) $root_id = $menu_item->menu_item_parent;
break;
}
}
}
}
$menu_item_parents = array();
foreach ( $sorted_menu_items as $key => $item ) {
// init menu_item_parents
if ( $item->ID == $root_id ) $menu_item_parents[] = $item->ID;
if ( in_array( $item->menu_item_parent, $menu_item_parents ) ) {
// part of sub-tree: keep!
$menu_item_parents[] = $item->ID;
} else if ( ! ( isset( $args->show_parent ) && in_array( $item->ID, $menu_item_parents ) ) ) {
// not part of sub-tree: away with it!
unset( $sorted_menu_items[$key] );
}
}
return $sorted_menu_items;
} else {
return $sorted_menu_items;
}
}
<?php
wp_nav_menu( array(
'menu' => 'Menu Name',
'sub_menu' => true
) );
<?php
$menu_to_count = wp_nav_menu( array(
'menu' => 'Menu Name',
'sub_menu' => true,
'echo' => false
) );
$menu_items = substr_count( $menu_to_count, 'class="menu-item ' );
if ( $menu_items != 0 ) echo $menu_to_count;
<?php
wp_nav_menu( array(
'menu' => 'Menu Name',
'sub_menu' => true,
'show_parent' => true
) );
@kokoruz
Copy link

kokoruz commented Jul 27, 2018

I was wondering if it is possible to only display the child menu of the parent of that child. ie., level 1 leaders to leve2, level3, and level4 and that is all I see but if I click on level 2 and can now see level2a, 2b, and 2c. Similar to how an accordion works but not necessarily like in AJAX but more traditionally. I just don't want to have a deep side bar menu due to setting the depth to 3. If this is possible please leave a comment below. Thank you.

@AdmireNL
Copy link

Great script! I would like to display the current menu ancestor as a title above the menu list. How can I do this? Currently I display the page parent as a title, but in some cases this is incorrect since page structure != menu structure.

@levymetal
Copy link
Author

@AdmireNL I'd probably use the show_parent => true flag, then apply appropriate styling to the first element. This only works if you want the title to appear directly above the menu; if you want it somewhere else you can extract the code that sets the $root_id variable into another function to get the root level menu item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment