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
    )
);


10 comments:

  1. You sir, are a god. I have been looking for this funktionality for so long, but everyone just makes workarounds by assining both pages and menus, but that sucks. Thanks a lot!

    ReplyDelete
  2. You just saved my life!

    ReplyDelete
  3. Anonymous6:32 AM

    This guy... amazing! Really appreciate it!

    ReplyDelete
  4. Its not working... menus are not listing the childrens or even not the pages which i have inserted in the menu.

    ReplyDelete
  5. Anonymous6:46 AM

    I have tested this solution and I was not able to get it to work either. I *have* seen some other walker classes with some success in the past, but nothing that has worked for me in all scenarios.

    I wrote my own plugin to handle split menus like this. My solution doesn't use a walker class, but instead lets you set a 'start depth' on your menu. My solution has a lot more power and flexibility than any other the other solutions I have seen to this problem.

    Check it out at https://mattkeys.me/products/wp-nav-plus/ if anyone is interested.

    ReplyDelete
  6. Anonymous6:46 AM

    I have tested this solution and I was not able to get it to work either. I *have* seen some other walker classes with some success in the past, but nothing that has worked for me in all scenarios.

    I wrote my own plugin to handle split menus like this. My solution doesn't use a walker class, but instead lets you set a 'start depth' on your menu. My solution has a lot more power and flexibility than any other the other solutions I have seen to this problem.

    Check it out at https://mattkeys.me/products/wp-nav-plus/ if anyone is interested.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. yes, I can integrate very easily. This is very helpful for me. Thank you.

    ReplyDelete
  9. Hi...Sir
    How to display top menu i.e parent and child menu in array format at least 3 subchild.

    ReplyDelete