4

I am using this code to show the custom menu subpages if you are on the parent page. But what this code also shows is a parent page on a page that has no sub menu, which I would like hidden. Basically only use this code if we are on a page that has a sub page,

class Selective_Walker extends Walker_Nav_Menu
{
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
        foreach ( $top_level_elements as $e ){  //changed by continent7
            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( !empty( $descend_test ) ) 
                $this->display_element( $e, $children_elements, 2, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
         /* removed by continent7
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }
        */
         return $output;
    }
}

in the template using:

wp_nav_menu( 
   array(
       'theme_location'=>'primary', 
       'walker'=>new Selective_Walker() 
   )
);
5
  • Does it need to be a Nav Menu Walker class? Or would it suffice to use wp_list_pages Commented Jun 19, 2012 at 9:21
  • Also - what if you're on a child page? Do you display their children only (if they have any)? Or the children of the 'root' parent? Commented Jun 19, 2012 at 9:22
  • I gave the wp_list_pages a shot, but it wasn´t showing me the sub pages, only if subpages were under the actually Pages menu. In my custom menu I have custom post types as sub pages for drop downs and those weren´t showing, this was the only code I found to work so far...
    – Nolan
    Commented Jun 19, 2012 at 11:08
  • I only want the children´s root parent.
    – Nolan
    Commented Jun 19, 2012 at 11:09
  • I have been using the solution to this question -> wordpress.stackexchange.com/questions/2802/… It adds a filter to wp_nav_menu that let's you pass a 'submenu' parameter.
    – gdaniel
    Commented Nov 12, 2014 at 17:46

2 Answers 2

3

I have had this exact same issue many times in the past with Wordpress. In other CMS's I've used the menus always had an option for the start_depth which made it really easy to implement a secondary or tertiary menu (split menu).

Wordpress doesn't include this function; and many of the solutions online use wp_list_pages which completely ignores the menu manager hierarchy.

After trying different walkers and widgets I finally decided to just write my own plugin that has the start_depth option in it.

you use it like this:

wp_nav_menu(array('theme_location' => 'primary_navigation', 'start_depth' => 1));

for anyone who is interested you can get it free on the WordPress plugin repository: https://wordpress.org/plugins/wp-nav-plus/

2

I've made a free plugin which solves this problem!

https://wordpress.org/plugins/wp-nav-menu-extended/

This plugin extends the native wp_nav_menu function and adds additional options:

  • level : (integer) (required for this plugin to work) The level of the navigation menu to show. If no child_of parameter is passed, it shows all the items of this level
  • child_of : (string|integer) (optional) Either the title or menu item ID of the parent in the menu whose direct children are to be shown

Sample Usage:

$defaults = array( 'theme_location' => 'main_menu', 'level' => 2, 'child_of' => 'About Us', );

wp_nav_menu( $defaults );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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