Take the 2-minute tour ×

I am making my first custom walker to build an accordion menu. To start with I used this example: http://bitacre.com/2025/custom-nav-menu-walker-for-wordpress-themes

There are two functions. First start_lvl and then start_el.

In start_el the ID get's implemented by $item->ID. Does anybody know how I can do this in start_lvl as well? I need to give the (surrounding lower level navigation) an ID so I can trigger it to collapse in the accordion menu.

What I'm trying to generate is something like this:

<a href="#collapse2">Titel 2</a>
<ul id="collapse2">Lower Level Menu 2</ul>
<a href="#collapse3">Titel 3</a>
<ul id="collapse3">Lower Level Menu  3</ul>

My code for the start_lvl function:

// add id's and classes to ul sub-menus
function start_lvl( &$output, $depth, $item ) {
    // depth dependent classes
    $indent = ( $depth > 0  ? str_repeat( "\t", $depth ) : '' ); // code indent
    $display_depth = ( $depth + 1); // because it counts the first submenu as 0
    $pgid = ; // How to get ID in here??
    $classes = array(
        ( $display_depth == 1  ? 'accordion-body collapse' : '' ),
        ( $display_depth % 2  ? 'menu-odd' : 'menu-even' ),
        ( $display_depth >=2 ? 'sub-sub-menu' : '' ),
        'menu-depth-' . $display_depth
    $ids = array(
        'collapse' . $pgid
    $class_names = implode( ' ', $classes );
    $id_name = implode( ' ', $ids );

    // build html
    $output .= "\n" . $indent . '<ul id="' . $id_name . '" class="' . $class_names . '">' . "\n";
share|improve this question
add comment

4 Answers

I had a similar problem and solved it by using a static variable inside the class:

static protected $menu_lvl; 

And then in the "display_element" I incremented the variable:


In my code I then referenced in the start_lvl function something like this:

$output .= "<ul id='level". self::$menu_lvl ."'>";

This doesn't use the page ID, but it does use a unique ID for UL statements that can be referenced by the javascript.

BTW - This is really just useful for nested accordions, or clickable nested dropdowns in the Roots Theme using Bootstrap for mobile apps.

share|improve this answer
add comment

I just had to do this in one of my themes... Since you don't have access to the $item variable at that stage of the Walker, you would want to store your current item in a more global scope when you do have access to it. The following code will make more sense... note: I've stripped everything but the relevant code.

class ThemeTruck_Nav_Walker extends Walker_Nav_Menu {
   private $curItem;

    var_dump($this->curItem );

    $this->curItem = $item;

share|improve this answer
This is the most elegant solution presented in this thread. Thanks Lane! –  Kevin C. May 31 '13 at 22:05
add comment

You can use the following filter in your start_el function and grub your argument in start_lvl function.

apply_filters( 'walker_nav_menu_start_lvl', $item_output, $item, $depth, $args->myarg=$item->title );

Please let me know know if it works.

share|improve this answer
Thanks for posting! I hope to find some time to work it out in the next few days but I am really busy with my study just now. I will get back to you with the result! –  Robert Bouten Sep 17 '12 at 20:09
add comment

You can simply add $page to the argument of the custom walker:

class My_Custom_Walker extends Walker_page {
    function start_el(&$output, $page, $depth, $args, $current_page) {
        if ( $depth )
            $indent = '';

        extract($args, EXTR_SKIP);

        $output .= $indent . 
            <a style="color:red" href="' . get_page_link($page->ID) . '" title="' . 
            esc_attr( wp_strip_all_tags( apply_filters( 'the_title', $page->post_title, $page->ID ) ) ) . '">' . 
            $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . '</a>';

Try the above and then before you call wp_list_pages(), add the custom walker class:

$MyWalker = new My_Custom_Walker();

Then, in the arguments for wp_list_pages:

wp_list_pages('walker' => $MyWalker)

Check and see if the output of the walker is red.

share|improve this answer
That is in function start_el, but it's apparently different in start_lvl because I can't put the same variables in there. Or at least not the same order. –  Robert Bouten Aug 16 '12 at 20:38
What are you trying to do with start_lvl? –  AlxVallejo Aug 16 '12 at 20:40
I am trying to give the <ul> an id="collapse102" with 102 the generated page ID. This way I can trigger it to collapse it in my accordion menu. –  Robert Bouten Aug 16 '12 at 20:50
Adding the id="collapse" works, but I can't get it to work to add the pageID as well. –  Robert Bouten Aug 16 '12 at 20:51
Do you mean that you want only specific IDs to be collapsed? I have an accordion tree for wp_list_pages and I don't need to alter start_lvl at all. –  AlxVallejo Aug 16 '12 at 20:54
show 6 more comments

Your Answer


