1

I'm using a custom nav walker to render out the main menu, during this I want to store the second level navigation items to use/ render out later in a separate area of the page.

I want these second level navigation items to display block, if you're currently in that section (i.e. if you're on 'services' or a subpage of 'services' then the submenu will display block). Also, if I hover over "services" I want the submenu to show.

Currently I've done the submenu in a separate custom nav walker - but the navigation only displays when you're in the section, not when you hover over the main menu item. Also, with how I currently have it setup it shows the menu background/ styles on pages that don't have submenus

This is my existing nav walker for the submenu only:

class MainSubmenuCustomWalker extends \Walker_Nav_Menu
{
    function start_lvl(&$output, $depth=0, $args=array())
    {
        if ($depth == 0) {
            return;
        }
        parent::start_lvl($output, $depth, $args);
    }

    function end_lvl(&$output, $depth=0, $args=array())
    {
        if ($depth == 0) {
            return;
        }
        parent::end_lvl($output, $depth,$args);
    }

    // Don't print top-level elements
    public function start_el(&$output, $item, $depth=0, $args=array(), $id=0)
    {
        if ($depth == 0) {
            return;
        }
        parent::start_el($output, $item, $depth, $args);
    }

    function end_el(&$output, $item, $depth=0, $args=array())
    {
        if ($depth == 0) {
            return;
        }
        parent::end_el($output, $item, $depth, $args);
    }

    function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output)
    {
        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );
        $current_class = array_intersect( $current_element_markers, $element->classes );
        $ancestor_of_current = !empty($current_class);

        if (0 == $depth && !$ancestor_of_current) {
            return;
        }

        $id = $element->ID;
        if (($max_depth == 0 || $max_depth > $depth+1) && isset($children_elements[$id])) {
            foreach ($children_elements[$id] as $child) {
                if (!isset($newlevel)) {
                    $newlevel = true;
                    //start the child delimiter
                    $cb_args = array_merge(array(&$output, $depth), $args);
                    call_user_func_array(array($this, 'start_lvl'), $cb_args);
                }
                parent::display_element($child, $children_elements, $max_depth, $depth + 1, $args, $output);
            }
            unset($children_elements[$id]);
        }

        if (isset($newlevel) && $newlevel) {
            //end the child delimiter
            $cb_args = array_merge(array(&$output, $depth), $args);
            call_user_func_array(array(&$this, 'end_lvl'), $cb_args);
        }
    }
}

It is being called from here, which renders the menu container even if there are no submenu items :(

<div class="main-submenu-navbar navbar navbar-default">
<div class="container">
    <div class="navbar-header">
        <button type="button"
        class="navbar-toggle collapsed"
        data-toggle="collapse"
        data-target="#main-submenu-collapse">
        <span class="sr-only">Toggle Navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
    </button>
</div>
<?php Menu::submenus(); ?>

1 Answer 1

0

Yesterday I had the same kind of problem and I decided to ditch the walker alltogether and use the wp_get_nav_menu_object and wp_get_nav_menu_items functions instead.

If you var_dump($menu_items) you can see which properties are available.

Here's a snippet of my code that builds the menu named 'main' for my twitter bootstrap menu:

    $menu_name = 'main'; // name of your menu
    $menu = wp_get_nav_menu_object($menu_name);

    $menu_items = wp_get_nav_menu_items($menu->term_id);



    $tmpWPMenu = ""; // string variable where the menu is stored

    // collect the menu-items (if any) and store them temporarily in 
    // the $tmpChildren array with the $key = id of parent

    $tmpChildren = array();
    foreach ( (array) $menu_items as $key => $menu_item ) {
        if (intval($menu_item->menu_item_parent) > 0) {
            $tmpChildren[$menu_item->menu_item_parent][] = $menu_item;
        }
    }

   // Now loop again and build it, 
   // when a matching ID is encountered in the $tmpChildren array, build the submenu:
    foreach ( (array) $menu_items as $key => $menu_item ) {
        $title = $menu_item->title;
        $url = $menu_item->url;

        if (intval($menu_item->menu_item_parent) == 0) {


            // Does $tmpChildren contain a $key that is the id of this menu-item?
            if (array_key_exists($menu_item->ID, $tmpChildren)) {

                $tmpWPMenu .= '<li class="dropdown">';
                $tmpWPMenu .= ' <a href="#" class="dropdown-toggle" data-toggle="dropdown"></i> '.$title.' <b class="caret"></b></a>';


                $tmpWPMenu .= ' <ul class="dropdown-menu">';
                foreach ($tmpChildren[$menu_item->ID] as $subMenuItem) {
                    $tmpWPMenu .= '<li><a href="/ik/"><!--<i class="glyphicon glyphicon-user"></i>--> ' . $subMenuItem->title . '</a></li>';
                }
                $tmpWPMenu .= ' </ul>';
                $tmpWPMenu .= '</li>';

            } else {

                $tmpWPMenu .= '<li>';
                $tmpWPMenu .= '<a href="#"></i> '.$title.' </a>';
                $tmpWPMenu .= '</li>';

            }

        }



    }

    // Do something with the $tmpWPMenu, in my case I pass it 
    // to the Smarty template engine that I use
    $tmpNavBarFindAndReplace['wp_menu'] = $tmpWPMenu;


    print $gBSOManager->pPageO->mRender($tmpNavBarFindAndReplace, 'mijn/navbar.html',true);

I hope this might help (or provide insight) :) Cheers, T

Your Answer

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

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