how to display part of a menu tree?

12,004

Solution 1

I've stopped to explore how to output custom part of worpress site taxonomy on the server-side. I just use jquery to copy active taxonomy branch from main menu and paste it to the page container I need.

Solution 2

You can write a filter_hook to accomplish this.

My method: create an additional start_in argument for wp_nav_menu using my custom hook:

# in functions.php add hook & hook function
add_filter("wp_nav_menu_objects",'my_wp_nav_menu_objects_start_in',10,2);

# filter_hook function to react on start_in argument
function my_wp_nav_menu_objects_start_in( $sorted_menu_items, $args ) {
    if(isset($args->start_in)) {
        $menu_item_parents = array();
        foreach( $sorted_menu_items as $key => $item ) {
            // init menu_item_parents
            if( $item->object_id == (int)$args->start_in ) $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 {
                // not part of sub-tree: away with it!
                unset($sorted_menu_items[$key]);
            }
        }
        return $sorted_menu_items;
    } else {
        return $sorted_menu_items;
    }
}

Next, in your template you just call wp_nav_menu with the additional start_in argument containing the ID of the page you want the children off:

wp_nav_menu( array( 
    'theme_location' => '<name of your menu>',
    'start_in' => $ID_of_page,
    'container' => false,
    'items_wrap' => '%3$s'
) );

Solution 3

I wrote this to print sub-navs of the pages you may be on. If you want to print out the sub-navigation for each of the pages, get the page parent instead of getting the ID. There would be more involved than that, but it's a start.

$menu = wp_get_nav_menu_items( 'Primary Menu' );
$post_ID = get_the_ID();
echo "<ul id='sub-nav'>";
foreach ($menu as $item) {
    if ($post_ID == $item->object_id) { $menu_parent = $item->ID; }
    if (isset($menu_parent) && $item->menu_item_parent == $menu_parent) {
         echo "<li><a href='" . $item->url . "'>". $item->title . "</a></li>";
     }
 }
echo "</ul>";`

Solution 4

Check out wp_list_pages(). It is useful for providing child navigation in the sidebar.

Solution 5

mac joost's answer is great, but I would add that if you want the parent item to print, then you shouldn't unset the parent, so line 18 needs to be adjusted accordingly:

    if($item->object_id != (int)$args->start_in) { unset($sorted_menu_items[$key]); }
Share:
12,004
Capacytron
Author by

Capacytron

Updated on June 05, 2022

Comments

  • Capacytron
    Capacytron almost 2 years

    I'm trying to deal with Wordpress 3.0. It's rather cool thing but I can't get on with one problem. For example, I have such menu tree. Menu tree is constructed from pages.

    Home
       news
       video
       audio
    Blog
       About author
       Favourite colors
          red
          blue
          green
    My car
       wheels
       tires
    

    The Idea is: main menu consists of root elements: home, blog, my car On the left side I would like to display children elements of current active root element.

    For exammple if person is on the "home" page, on the left part he should see:

      news
      video
      audio
    

    If user is on the "Blog" page, he should see:

    About author
           Favourite colors
              red
              blue
              green
    

    I can't find an API to do that. Can you sugest me please where can I find it?

    UPD: @Jason McCreary I've seen I've seen wp_list_pages() and tried it. I din't get how can I use it: Please, see my template for a page:

        <?php
    /*
     Template Name: page_news
    
     * @package WordPress
     * @subpackage Twenty_Ten
     * @since Twenty Ten 1.0
     */
    
    get_header(); ?>
    <h1>page_news</h1>
    <h1>Children menu:</h1>
    <?php wp_list_pages('echo=0&child_of=8&title_li='); ?>
    <div id="container">
            <div id="content" role="main">
    
            <?php
            /** Get category id by name*/
            //$catId = get_category_by_slug('news')->term_id;
            query_posts('category_name=news');
            get_template_part( 'loop', 'page' );
            ?>
    
            </div><!-- #content -->
    </div><!-- #container -->
    
    <?php get_sidebar(); ?>
    <?php get_footer(); ?>
    

    See this line of code:

    <?php wp_list_pages('echo=0&child_of=8&title_li='); ?>
    

    I do have the page with id=8 (I see it in URL). Page with id=8 has several children. I want to print them, but they are not printed. The output of the function wp_list_pages() is nothing. I don't know why... :(

  • Capacytron
    Capacytron about 13 years
    So main idea is that I don't want just list of pages. I want to print sub-navigation starting from specified id. For example, I do specify pageId of page named "Blog" and I do get sub-navigation of a blog branch.
  • tsdexter
    tsdexter almost 11 years
    thanks a bunch, this is by far the best solution as it still uses the nav menu/custom walker etc to layout my sub menus. Should be accepted answer.
  • Shahar
    Shahar almost 10 years
    Good idea, but bad approach. In most cases it's better to deliver everything you can on the server side, and only stuff you must on the client side.
  • Shahar
    Shahar almost 10 years
    when setting 'child_of' in wp_list_page() the function will return children of a post and not children of the parent menu.
  • mikevoermans
    mikevoermans almost 10 years
    So happy to see someone answer a menu question by using the wp_nav_menu as it should be. So tired of people saying wp_list_pages like it is the same thing.
  • Joel Stransky
    Joel Stransky about 7 years
    This is genius! I'm trying to move my WP theming strategy in a direction where everything is organized in the menu vs a combination of it and hierarchical post types. I've already done some nice things with menu_order and post meta based on menu position but this was the missing link. Bravo.