Sunday, November 13, 2011

Creating separate sub menu in WordPress 3

I needed to create a split menu for one of my projects where top level menu items were in a horizontal menu and children of active menu in a sidebar. Its a super simple task in Joomla but I couldn't find anything out of the box in WordPress.



I managed to resolve this issue using wp_list_pages, but it was not sorted according to custom menu sort order. So I made this simple custom walker and it worked.

(This link helped me in adding has_children property to menu items).


class SplitMenu_Walker_Nav_Menu extends Walker_Nav_Menu {
 var $startMenu = false;
 
 function start_lvl(&$output, $depth) {
  
 }

 function end_lvl(&$output, $depth) {
  $this->startMenu = false;
 }
 
 function start_el(&$output, $item, $depth, $args) {
  if(($args->has_children && $item->current) || $item->current_item_parent)
   $this->startMenu = true;
  
  if($this->startMenu && $depth > 0)
    parent::start_el($output, $item, $depth, $args);
 }

 function end_el(&$output, $item, $depth) {
  if( $this->startMenu )
    parent::end_el($output, $item, $depth);
 }
 
 function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $id_field = $this->db_fields['id'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
}

This code is tested with single level of sub menus only.

How to use:

  1. Copy above code and paste into your theme's functions.php
  2. Pass an object of walker class to your 'wp_nav_menu' function:

wp_nav_menu(
    array (
        'menu'            => 'main-menu',
        'walker'          => new SplitMenu_Walker_Nav_Menu
    )
);