Menu item added in wp_nav_menu_items filter is never highlighted

In a Twenty Thirteen child theme I append a menu item (a link to /player-number page template, where the number is different for each user and represents her or his id in a game database) using the wp_nav_menu_items hook:

function my_nav_menu_items( $items ) {
    $profile = sprintf('li id="menu-item-32" 
        class="menu-item menu-item-type-custom 
        menu-item-object-custom menu-item-32"
        a href="/player-%d/#navbar"Profile/a/li', 
        42); // 42 is just a placeholder here, representing user id

    return $items . $profile;
}

add_filter( 'wp_nav_menu_items', 'my_nav_menu_items' );

And that item is visible and clickable in the primary-menu, but for some reason it is never highlighted (apologies for non-english text in the screenshot):

I.e. when I click at any other menu entry - it changes its color to reddish one and the font slant to italics:

But the last menu item does not do that, why?

UPDATE:

The wp_nav_menu_objects filter seems to be more suitable for the task of adding a menu item and I have tried using it in my /wp-content/themes/twentythirteen-child/functions.php file:

function my_nav_menu_objects( $sorted_menu_items ) 
{
    $link = array (
        'title'            = 'Profile',
        'menu_item_parent' = 0,
        'ID'               = 32,
        'url'              = '/player-42',
    );
    $sorted_menu_items[] = (object) $link;
    error_log(print_r($sorted_menu_items, TRUE));
    return $sorted_menu_items;
}

add_filter( 'wp_nav_menu_objects', 'my_nav_menu_objects' );

but it suffers the same problem: the menu item is added, but it is not highlighted (the CSS style current-menu-item for that is missing) when selected.

UPDATE 2:

Also I have tried adding a menu item called "Profile" manually and then searching and replacing its url with the following code:

function my_nav_menu_objects( $sorted_menu_items )
{
    foreach ( $sorted_menu_items as $item ) {
            error_log(print_r($item, TRUE));

            if ( $item-title == 'Profile' ) {
                $item-url = '/player-42';
                break;
            }
    }

    return $sorted_menu_items;
}

add_filter( 'wp_nav_menu_objects', 'my_nav_menu_objects' );

with the same effect (the URL has changed, but CSS highlighting is missing, when that URL is selected).

Topic theme-twenty-thirteen filters hooks theme-development menus Wordpress

Category Web


@AlexanderFarber, there are many way to attach attribute class under wp_nav_menu link. I agree with @Sumit, adding page links in Appearance > Menu WordPress take care of current-menu-item class or current_page_item class. Also, this way is best practice to handle your nav menu in the future.

Create dynamic link in wp_nav_menu

Since your question related to this answer, then you have a Page with player as slug. My approach, after I add those page as menu in Appearance > Menu ( then change label with 'Profile' ), I will use filter nav_menu_link_attributes to make this page have dynamic link. As your question, you use current user id to make it dynamics. Take a look this sample code, say 7 is post/page ID as target:

add_filter( 'nav_menu_link_attributes', function( $atts, $item, $args, $depth )
{
    // check our nav_menu
    if ( is_object( $args ) && is_object( $item ) && 'primary-menu' == $args->menu_id )
    {
        $post_id = 7; // Define Post or Page ID
        $user    = wp_get_current_user();
        if ( 0 < $user->ID && $post_id == $item->object_id )
            $atts['href'] = esc_url( user_trailingslashit( untrailingslashit( $item->url ) . '-' . $user->ID ) );
    }
    return $atts;
} 10, 4 );

You need to check which menu before you make change, since your filter will effect another menu in the same page. By this approach you don't get trouble in attribute ( class or id theme css related ) of the current page.

Answer related your code

Yes I know you need to add custom link by filter wp_nav_menu_items and add class attribute for the current page, almost the same with your answer. Since it related to Page, I use current_page_item as class attribute that match with css TwentyThirteen to make highlight of item nav menu.

add_filter( 'wp_nav_menu_items', 'my_nav_menu_items', 10, 2 );
function my_nav_menu_items( $items, $args )
{
    if ( is_object( $args ) && 'primary-menu' == $args->menu_id )
    {
            $user         = wp_get_current_user();
            $with_user_id = ( 0 != $user->ID ) ? '-' . $user->ID : '';
            
            $post_id      = 7; // Post or Page ID
            $class        = ( is_page( $post_id ) ) ? 'current_page_item' : '';
            
            $items .= sprintf( '<li id="menu-item-32" class="menu-item menu-item-type-custom 
            menu-item-object-custom %1$s menu-item-32"><a href="%2$s">%3$s</a></li>',
                sanitize_html_class( $class ),
                esc_url( user_trailingslashit( untrailingslashit( get_page_link( $post_id ) ) . $with_user_id  ) ),
                __( 'Profile', 'textdomain' )
            );
    }
    return $items;
}

You can tweak the code to adjust with your current project. I hope this helps.


Here is my own solution - in the /wp-content/themes/twentythirteen-child/functions.php file add the current-menu-item CSS style if the page slug is player:

function my_nav_menu_items( $items ) 
{
    $profile = sprintf('<li class="menu-item 
        menu-item-type-custom 
        menu-item-object-custom 
        %s"><a href="/player-%d/#navbar">Profile</a></li>', 
        ( is_page( 'player' ) ? 'current-menu-item' : '' ),
        42);
    return $items . $profile;
}

add_filter( 'wp_nav_menu_items', 'my_nav_menu_items' );

A more specific page check would be: is_page( array ( 42, 'player' ) )


The other pages show a 'current menu item' css state:

.nav-menu .current_page_item > a, .nav-menu .current_page_ancestor > a, .nav-menu .current-menu-item > a, .nav-menu .current-menu-ancestor > a {
   color: #bc360a;
   font-style: italic;

This page is showing as 'page-id-32'. If that corresponds to the page in the menu it should show the 'current page item' css. Otherwise you need to get the class 'current-menu-item' in the css somehow when you are on that page. For instance, if you change:

sprintf('<li id="menu-item-32" 
    class="menu-item menu-item-type-custom 
    menu-item-object-custom menu-item-32">

to

sprintf('<li id="menu-item-32" 
    class="menu-item menu-item-type-custom 
    menu-item-object-custom current-menu-item">

It will do the job, but I think that would show as 'always' the current page.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.