Didn’t thought I would have to ask this question. But yes, it’s true. It seems you can’t have a separate child menu in WordPress?
I’m absolutely not a beginner on WordPress. Have worked and developed in it for years.
However, it might be possible to do a big walkaround to get the separate child/sub menu. But what I would like to get an answer of here is more like;
Is it really true there’s no simple built-in solution?
I have really searched on this site and other sites for answers but struggled to find an answer. It seems to be all about drop downs. I’m soooo tired of drop downs now!
Can say I’m running Woocommerce as well. But no, there was no answer in their’s documentation either. A lot about “secondary menus”. But that’s not the same. I need the parent child relationship.
EDIT:
Following code example and output example has been added/changed to work as an example of a case scenario:
Here is my code:
<nav class="parent">
<?php
wp_nav_menu(
array(
'theme_location' => 'primary',
'container_class' => 'primary-navigation',
)
);
?>
</nav><!-- #parent -->
// Following menu should only be shown if the selected menu item from the above menu has child items. Show them here below. How do I make these two menus to have a connection to each other?
<nav class="child">
<?php
wp_nav_menu(
array(
'theme_location' => 'primary',
'container_class' => 'primary-child-navigation',
)
);
?>
</nav><!-- #child -->
The output result would be something like this:
Home | Bags | Shoes | Hats
Backpacks | Weekend Bags | Travel Cases | Handhelds
And now we are on the Weekend Bag page!
Simple as that!
Edit 2:
First problem is that depth
attribute doesn’t seems to work for wp_nav_menu()
. Can’t have just top level?
4 Answers
Found the solution. Put this in your function.php file:
// 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;
}
}
Then use it this way:
<?php
wp_nav_menu(
array(
'theme_location' => 'primary',
'container_class' => 'primary-navigation',
'depth' => 1
)
);
wp_nav_menu(
array(
'theme_location' => 'primary',
'container_class' => 'primary-child-navigation',
'sub_menu' => true
)
);
?>