WordPress.org

Ready to get started?Download WordPress

Forums

wp_nav_menu: List only 2nd level (separate submenu)? (54 posts)

  1. feggbert
    Member
    Posted 4 years ago #

    Hi all,

    I am currently fiddling around with the new wp_nav_menu. So far I like it. But I am having troubles building a separate vertical navigation that shows the parents sub-pages only (as definded in the Menu settings in the backend). Is this possible with this new functionality? Or do I still have to use wp_list_pages? This would be quite inconvenient, since I would have to manage another hiearchy in the pages or category settings. I've looked around the web for a solution but couldn't find a fix. I guess v3.0 is yet too new.

    Thanks for a quick note.

    Regards,

    Felix

  2. sushicodeur
    Member
    Posted 4 years ago #

    I'm facing exactly the same problem, and didn't find any satisfactory solution. Played with the Walker_Nav_Menu and the filter wp_nav_menu_items with no luck.

    All I found at the moment is a hack using css, but I'm still looking for a nicer solution.

    ul.sister-pages li { display:none; }
    ul.sister-pages li.current-menu-ancestor,
    ul.sister-pages li.current-menu-ancestor li { display:block; }
  3. feggbert
    Member
    Posted 4 years ago #

    Wouldn't it be possible to use a pgrep_replace? I have no idea how to set the RegExp...

  4. sushicodeur
    Member
    Posted 4 years ago #

    I think I got it. I created a custom walker for this, that displays only the menu items that have the classes "current-menu-item", "current-menu-parent", "current-menu-ancestor", and all their descendants. It works fine for me, but isn't fully tested yet.

    [Code moderated as per the Forum Rules. Please use the pastebin]

  5. sushicodeur
    Member
    Posted 4 years ago #

    I've been a bit to quick, end_el and end_lvl should be overidden as well in Custom_Walker_Nav_Sub_Menu :

    [Code moderated as per the Forum Rules. Please use the pastebin]

  6. feggbert
    Member
    Posted 4 years ago #

    Dude, you're the man! Seems to work nicely for my menu, except for menuitems without sub-hierarchy there is an error

    Warning: in_array() [function.in-array]: Wrong datatype for second argument in /wp-content/themes/aoc/functions.php on line 80

    Which refers to this line of code:

    // Checks if the current element is in the current selection
          if (strpos($class_names, 'current-menu-item')
          || strpos($class_names, 'current-menu-parent')
          || strpos($class_names, 'current-menu-ancestor')
          || in_array( $item->menu_item_parent, $found_parents ) ) {

    This also occurs in a few more lines further down all using $found_parents...

    Thanks for your great help! (Too bad this functionality is not implemented in wp_nav_menu from the beginning...)

    Felix

  7. sushicodeur
    Member
    Posted 4 years ago #

    oops, you're true, change the condition with :

    if (strpos($class_names, 'current-menu-item')
        || strpos($class_names, 'current-menu-parent')
        || strpos($class_names, 'current-menu-ancestor')
        || (is_array($found_parents) && in_array( $item->menu_item_parent, $found_parents )) ) {

    Then, in end_el function, change the condition with :

    if ( is_array($found_parents) && in_array( $item->ID, $found_parents ) ) {

    Should be fine then...

  8. stuckish
    Member
    Posted 4 years ago #

    It is maybe not exactly the same problem but i solved this with jQuery. Just hide all sub-menus and then show the sub-menu if the parent happens to be .current_page_item.

    $(".sub-menu").hide();
    $(".current_page_item .sub-menu").show();

    http://codepolice.net/2010/06/28/only-show-the-sub-menu-when-the-parent-is-selected-with-the-new-wp_nav_menu-in-wordpress-3-0/

  9. feggbert
    Member
    Posted 4 years ago #

    Well thanks again for the nice snippet. It works nicely! Maybe you can tell me one more thing: How do I get rid of the parent item in the generated list...

    Right now the list hierarchy is like this:

    <ul><li>
    <a> Parent </a>
    <ul>
    <li> Child 1 </li>
    <li> Child 2 </li>
    <li> Child 3 </li>
    </ul>
    </li></ul>

    So basically I don't need the <a> Parent </a> or even the surrounding <ul> and
    <li>....

    Any idea? Still can't believe this function isn't built in from the beginning...

    Thanks a lot!

    Felix

  10. petersom3000
    Member
    Posted 4 years ago #

    I think sushicodeur's is the way to go.
    Here are two custom walkers, one to extract the current sub-menu, the other to omit it

    [Code moderated as per the Forum Rules. Please use the pastebin]

  11. johnnybebopcool
    Member
    Posted 4 years ago #

    I have been working on this for days now...thank you so much for figuring this out!

    I second feggbert though...is there a way to get rid of/hide the top level parent link?

  12. feggbert
    Member
    Posted 4 years ago #

    johnny, at the moment i just hid it through css...not pretty but works for my client...

  13. Kaiey
    Member
    Posted 4 years ago #

    I've had some much trouble with this. I was very surprised it wasn't included in the wp_nav_menu function.

    The custom walker petersom3000 posted works great, except it's only limited to a navigation depth of 2 (which I can work with, but if it was able to just filter the sub menu of the current parent, regardless of depth, it would rock!).

    Also, I too wish to hide the parent link as mentioned above. Can the custom walker be modified to support this? ...or what CSS are you guys using to hide it?

    Is it also possible for someone to create a walker that lets you exclude pages/categories based on their ID (I'm having trouble doing this).

    Thanks!

  14. Bradford
    Member
    Posted 4 years ago #

    That custom walker is great however it's problematic when it's returning the parent element. I'm not good enough at PHP at this point to fix that but it seems trivial enough. If you know how to do it please include that at least as an argument. Thanks a lot! This is kind of silly that it isn't included in wp_nav_menu to begin with.

  15. Bradford
    Member
    Posted 4 years ago #

    I've come up with a workaround that is a little janky but it works for me, you can try and maybe it will work for you.

    [Code moderated as per the Forum Rules. Please use the pastebin]

    Basically it tells the wp_nav_menu to return a string instead of echo. Next it plugs that into an XML tree. After that it counts how many
    <li> elements there are. If there are more than 1 (more than the parent menu), it will grab the child <ul> element and return that as XML. It works great for me but ideally this would be handled by wp_nav_menu natively.

  16. nerdfactor
    Member
    Posted 4 years ago #

    i just sort of fixed @elBranfords problem inside the walker. don't know how "nice" this fix is, but it works for now with my site. the fix is inside the start_el function, so there is no change in anything else.

    [Code moderated as per the Forum Rules. Please use the pastebin]

    it checks if the current item has the same id as the parent item and than skips it. i set the parent id to 0 (no parent id), so it only works with two level navigations. maybe someone finds a way to find the proper parent id (i didn't really look for one). then it would work for navigations with more then two levels.

  17. glebis
    Member
    Posted 4 years ago #

    Here's my solution for 3 level navigation, based on @elBradford method:


    $menu_string = wp_nav_menu($menu_args);
    $xml = new SimpleXMLElement($menu_string);
    $i = 0;
    foreach($xml->li as $li) {
        $classes = array('current-page-ancestor','current-menu-item','current-menu-parent');
        if(strstr($li['class'],'current-page-ancestor') || strstr($li['class'],'current-menu-item') || strstr($li['class'],'current-menu-parent')) {
            $out= $i;
    };
    $i++;
    }
    
    if(!empty($out)) {echo '<ul>'. $xml->li[$out]->asXML() . '</ul>';}

  18. holypixel
    Member
    Posted 4 years ago #

    Wow this is amazing... thank you sushicodeur and everyone else for your hard work!

    One issue I have found is if the item (page/category etc) you are visiting appears in multiple trees it will list all trees in the menu.

    For example with the following custom menu...

    PARENT 1 --- PARENT 2 --- PARENT 3
    ITEM A ----- ITEM B ----- ITEM C
    ITEM D ----- ITEM D ----- ITEM F
    ITEM G ----- ITEM H ----- ITEM I

    ... the walker that everyone has so kindly worked on will generate a tree showing all the children (and parents) of any parent which contains duplicate items, so in the above example, as item D appears as a child twice, a list will be generated like so...

    PARENT 1
    ITEM A
    ITEM D
    ITEM G
    PARENT 2
    ITEM B
    ITEM D
    ITEM H

    If anyone has any suggestions on how to limit the results to just one tree I would be greatly appreciative!

  19. Jenn
    Member
    Posted 4 years ago #

    This is almost exactly what I need. I'm having the same issue as the user above. Check out this link:

    http://ht.ly/2BY46

    Does anyone have an idea of how the code can be tweaked to only show the links for the section it appears in the menu?

    Before I implemented this code, I already had a function in place that listed child pages if in a parent. But, the client wants certain child pages to be in more than one category.

  20. Bradford
    Member
    Posted 4 years ago #

    Jenny Jane,

    On my browser I'm not seeing any of the menu items being highlighted. I'm assuming you have the proper CSS catching the class of the selected menu item and modifying its appearance appropriately?

    Actually, I'm not really sure what your looking to do.

    Bradford

  21. Jenn
    Member
    Posted 4 years ago #

    Did you look in the sidebar? :)

    You are currently on Transcripts, which in the menu can be found under both Parents and Students. Because Transcripts appears under two main nav items, it lists both sections in the sidebar.

    I'm looking for a way to only list the children that I specified under either Parents or Students.

    The more I think about it, the more it seems unlikely to be achievable. No matter what, Transcripts is only one page. How would you specify which sub-menu to display? Seems like it would have to be dependent on which link they clicked on the menu...

    Oh well!

  22. samirtuladhar
    Member
    Posted 4 years ago #

    Thanks Guys to putting this code together. Worked for me.

  23. akramabs
    Member
    Posted 3 years ago #

    Hello,

    What about this small snippet? it works fine.. i made it. it is listing only 2nd level of menu.

    $menu = wp_nav_menu( array( 'menu_id' => 'nav-2', 'theme_location' => 'primary', 'echo'=>0 ) );
    					$menu = preg_match_all('/(<ul class="sub-menu">.*<\/ul>)(.*<\/li>)/s',$menu,$matches);
    					$menu = $matches[1][0];
    					$menu = str_replace('class="sub-menu"','id="nav-2"',$menu);
    					echo $menu;
  24. jasonlancaster
    Member
    Posted 3 years ago #

    Nice job everyone, especially sushicodeur for the original class. Custom_Walker_Nav_Sub_Menu is PERFECT.

    Too bad it was so hard to find this thread and this functionality wasn't included in the nav_menu function to begin with!

  25. erwanpia
    Member
    Posted 3 years ago #

    Hi, I was tryin new Custom_Walker_Nav_Sub_Menu() in my menu widget "s walker input but I get the following error

    Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'new Custom_Walker_Nav_Sub_Menu()::walk' was given in /home/www/wp-includes/nav-menu-template.php on line 443

    who knows how to use the Custom_Walker_Nav_Sub_Menu from within widgets ?

    thanks

  26. Just MOE
    Member
    Posted 3 years ago #

    @feggbert
    @johnnybebopcool
    @Kaiey

    I wanted to hide the parent element too. I created a solution for my scenario. I have a sub menu that I list inline below the main navigation tabs. I only want the navigation listed if it's the current tab of course. I override the WALKER class function "walk" instead of the level and element tag functions like Sushi did.

    The result is only the sub navigation and no extra
    UL tags. You use the same arguments as sushi does for the original walker he created.

    [Code moderated as per the Forum Rules. Please use the pastebin]

  27. Just MOE
    Member
    Posted 3 years ago #

    Ah! Alright, that solution above stinks. I found a better solution that's much simpler and works perfectly.

    http://www.darrenhoyt.com/2008/02/12/creating-two-tiered-conditional-navigation-in-wordpress/

  28. Frankie Jarrett
    Member
    Posted 3 years ago #

    Ah! Alright, that solution above stinks. I found a better solution that's much simpler and works perfectly.

    @Just MOE

    that's simple but it doesn't utilize wp_nav_menu functionality...isn't that what's being discussed here?

    //Frankie

  29. XGhozt
    Member
    Posted 3 years ago #

    Anyone know of any of the scripts here allow me to only display the sub menu of a specific parent menu? For example, if there's 3 menu item's, home, about, contact..

    Let's say there's 5 sub menu links under "about".

    How can I use wp_nav_menu to only display the items under the "about" menu item?

  30. Cole Slaw
    Member
    Posted 3 years ago #

    I can recommend the thread on Stack Exchange.

    The answers from Rarst works perfect.

Topic Closed

This topic has been closed to new replies.

About this Topic