I have this loop that simply shows all child pages of the current page:
<?php $args = array( 'parent' => $post->ID, 'post_type' => 'page', 'sort_order' => 'ASC' ); $pages = get_pages($args); ?> <?php foreach( $pages as $page ) { ?> <div> <p><?php echo $page->post_title; ?></p> </div> <?php } ?>
The Nav for this page looks like this:
Parent Page - Child page - Child page - Child page - Custom Link (added in appearance > menus) - Custom link (added in appearance > menus) - Page which has another parent (added in appearance > menus)
The code above correctly shows all of the direct child pages, but I would like it to show the custom links and other page I have added to the menu dropdown.
Ive tried playing with wp_get_nav_menu_items
in place of get_pages
and also using 'post_type' => 'page'
but I can’t seem to get this working correctly. I can either show a full list of all pages or just the direct child pages.
Can anyone tell me where I’m going wrong please? I seems like it should be a really easy thing to do…
Advertisement
Answer
Ok, I’ve found a way to get this to work using a custom walker class inside the functions.php file, like so:
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; } }
Then using this to my template page to simply the menu:
<?php $menuParameters = array( 'theme_location' =>'primary', 'walker'=>new Selective_Walker() ); echo wp_nav_menu( $menuParameters ); ?>
This helpfully shows the current page title as well as ALL of the sub nav items, not just the page items.