0

I am trying to override wp menu markup and add additional div around each sub-menu ul.

Something like this

<ul>
    <li><a>Coffee</li>
    <li><a>Tea</a>
        <div class="holder">
            <ul class="sub-menu">
                <li><a>Black tea</a></li>
                <li><a>Green tea</a></li>
            </ul>
        </div>
    </li>
    <li><a>Milk</a>
        <div class="holder">
            <ul class="sub-menu">
                <li><a>Red</a></li>
                <li><a>Blue</a></li>
            </ul>
        </div>
    </li>
</ul>

Is it possible to do this inside ?

$defaults = array(
    'theme_location'  => 'primary',
    'menu'            => '',
    'container'       => 'div',
    'container_class' => '',
    'container_id'    => 'mega-menu',
    'menu_class'      => 'mega',
    'menu_id'         => '',
    'echo'            => true,
    'fallback_cb'     => 'wp_page_menu',
    'before'          => '',
    'after'           => '',
    'link_before'     => '',
    'link_after'      => '',
    'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>',
    'depth'           => 0,
    'walker'          => ''
);

Any help is appreciated.

2 Answers 2

2

OK got it. For anyone who needs to do this , it is best you extend Walker_Nav_Menu class if you just need to add things to existing wp menu structure. Otherwise if you are extending Walker class you kinda have to rebuild the menu completely.

Include this class

class Walker_Extend_Menu extends Walker_Nav_Menu {

    // Tell Walker where to inherit it's parent and id values
    var $db_fields = array(
        'parent' => 'menu_item_parent', 
        'id'     => 'db_id' 
    );

    /**
     * Starts the list before the elements are added.
     *
     * @see Walker::start_lvl()
     *
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int    $depth  Depth of menu item. Used for padding.
     * @param array  $args   An array of arguments. @see wp_nav_menu()
     */
    public function start_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<div class=\"holder\">\n$indent<ul class=\"sub-menu\">\n";
    }

    /**
     * Ends the list of after the elements are added.
     *
     * @see Walker::end_lvl()
     *
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int    $depth  Depth of menu item. Used for padding.
     * @param array  $args   An array of arguments. @see wp_nav_menu()
     */
    public function end_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul>\n</div>\n";
    }

}

And call your walker in wp_nav_menu

$defaults = array(
    'theme_location'  => 'primary',
    'menu'            => '',
    'container'       => 'div',
    'container_class' => '',
    'container_id'    => 'mega-menu',
    'menu_class'      => 'mega',
    'menu_id'         => '',
    'echo'            => true,
    'fallback_cb'     => 'wp_page_menu',
    'before'          => '',
    'after'           => '',
    'link_before'     => '',
    'link_after'      => '',
    'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>',
    'depth'           => 0,
    'walker'          => new Walker_Extend_Menu ()
);
1

I believe what you are looking for is a custom nav walker to control your HTML structure.

The WP Codex article lists a good example for controlling the HTML structure of a menu http://codex.wordpress.org/Class_Reference/Walker#General_Menu_Example

// Tell Walker where to inherit it's parent and id values
var $db_fields = array(
    'parent' => 'menu_item_parent', 
    'id'     => 'db_id' 
);

/**
 * At the start of each element, output a <li> and <a> tag structure.
 * 
 * Note: Menu objects include url and title properties, so we will use those.
 */
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    $output .= sprintf( "\n<li><a href='%s'%s>%s</a></li>\n",
        $item->url,
        ( $item->object_id === get_the_ID() ) ? ' class="current"' : '',
        $item->title
    );
}

}

I will see if I can test up an example that solves your submenu challenge directly.

2
  • thnx bud, i just ran in to the walker extend class and trying to make sense of it.
    – Benn
    Commented Feb 10, 2015 at 14:51
  • 1
    It is definitely second level PHP stuff! Abstract classes give me tired head.
    – jdm2112
    Commented Feb 10, 2015 at 15:09

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.