2

I would like to add classes containing the page id numbers to the <li> items in my nav menu. Similar classes are generated by wp_page_menu() but for some reason they're not generated by wp_nav_menu().

I thought perhaps I could use the "walker" functionality (which I'm only now discovering) to add a custom class to the <li> tags, and use get_post_meta( $item->ID, '_menu_item_object_id', true ); to get the ID numbers, but I'm having a hell of a time figuring out how to do it. Everyone on the various forums seems to have questions about using the walker class for sub-menus and so forth and I've tried various codes from my searches but nothing is working. I just need a custom class with the page ID in each <li> tag.

My current menu code is the basic:

function abdmenu_nav()
{
wp_nav_menu(
array(
    'theme_location'  => 'header-menu',
    'menu'            => '',
    'container'       => 'div',
    'container_class' => 'menu-{menu slug}-container',
    'container_id'    => '',
    'menu_class'      => 'menu',
    'menu_id'         => '',
    'echo'            => true,
    'fallback_cb'     => 'wp_page_menu',
    'before'          => '',
    'after'           => '',
    'link_before'     => '',
    'link_after'      => '',
    'items_wrap'      => '<ul>%3$s</ul>',
    'depth'           => 0,
    'walker'          => ''
    )
);
}

I'm sure this is simpler than I'm making it but I've never dealt with the walker class before. I can't even find anything about whether it's even necessary for what I'm trying to do. If it is, how would I set it up?

4

We can add custom nav menu classes through the nav_menu_css_class filter.

Example:

The following should add the CSS class wpse-object-id-{object_id} to the <li> tags:

// Add filter
add_filter( 'nav_menu_css_class', 'wpse_menu_item_id_class', 10, 2 ); 

// Your navigational menu
wp_nav_menu( $args );

// Remove filter
remove_filter( 'nav_menu_css_class', 'wpse_menu_item_id_class', 10, 2 );

where we define the filter callback as:

/**
 * Custom Nav Menu Class For Page ID
 */
function wpse_menu_item_id_class( $classes, $item )
{
    if( isset( $item->object_id ) )
        $classes[] = sprintf( 'wpse-object-id-%d', $item->object_id );

    return $classes;
}

Here the object_id attribute should give us the corresponding page/post ID.

We can see that this attribute originates from the wp_setup_nav_menu_item() core function:

$menu_item->object_id = ! isset( $menu_item->object_id ) 
    ? get_post_meta( $menu_item->ID, '_menu_item_object_id', true ) 
    : $menu_item->object_id;
  • This worked brilliantly, thank you so much. Right now I have the function and then the add_filter() call, which is working. Do I need to remove something as well though? I'm not sure why I need the remove_filter() one. Also just a typo - return $classes is missing a semicolon at the end. – Shoelaced Aug 31 '16 at 20:14
  • Glad to hear it worked for you. Thanks, fixed the typo and updated the answer. We need to remove our filter to avoid affecting other menus on the page. @Shoelaced – birgire Aug 31 '16 at 20:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.