Custom Walker: how to get ID in function start_lvl

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.

Read More

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(
        'sub-menu',
        ( $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";
}

Related posts

Leave a Reply

3 comments

  1. 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 at the moment 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;
    
      // retrieve the curItem
      function start_lvl(&$output, $depth = 0, $args = array()) {
        var_dump($this->curItem );
      }
    
      // store the curItem
      function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
        $this->curItem = $item;
      }
    
     }
    
  2. 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.

  3. 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 = str_repeat("t", $depth);
            else
                $indent = '';
    
            extract($args, EXTR_SKIP);
    
            $output .= $indent . 
                '<li>
                <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.