How to add a data attribute to a WordPress menu item

I’m Twitter Bootstrap and need to add data-toggle=”modal” attribute to the a tag of menu link. Upon searching most all results reference doing a walking for Twitter Bootstrap dropdown menus however this menu has no dropdowns and I only need to add the particular attribute.

Next I found this: Add custom attributes to menu items without plugin which is very helpful as it appears in WordPress 3.6+ we no longer have to do long complex walkers and instead can use this: http://codex.wordpress.org/Plugin_API/Filter_Reference/nav_menu_link_attributes

Read More

However as of this running that API reference is quite bare and offers no examples and since it’s so new there are very few references to it on Google.

I tried this first:

add_filter( 'nav_menu_link_attributes', 'mywp_contact_menu_atts', 10, 3 );

function pb_contact_menu_atts( $atts, $item, $args )
{
    // inspect $item, then …
    $atts['data-toggle'] = 'modal';
    return $atts;
}

and that does work however it as expected adds the attribute to all the a tags in the menu. So I’m trying to figure out how to target one menu item with #menu-item-7857 a or such.

Does anyone know where to find an example of targeting a menu item or able to determine how to basd on the information that’s in the above linked API reference?

To note, I did find the following one example but it only targets items that have children which does not help but may be in the right direction:

add_filter('nav_menu_link_attributes', function($atts, $item, $args) {
    if ( $args->has_children )
    {
        $atts['data-toggle'] = 'dropdown';
        $atts['class'] = 'dropdown-toggle';
    }

    return $atts;
}, 10, 3);

UPDATE – The only answer below sounds like it’s on to something but from it wasn’t able to determine how to actually find the number to target my specific link and where/how to add that conditional in a working example. Added a comment but didn’t hear back. Since been about 18 days thought I’d see if a bounty would help.

When I look at the code for the link I want to target:

<li id="menu-item-7858" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-7858"><a href="#" data-toggle="modal">Chat</a></li>

I see the number 7858 so thinking maybe that is the number I should be targeting.

But when I try for instance:

add_filter( 'nav_menu_link_attributes', 'my_chat_menu_atts', 10, 3 );


function my_chat_menu_atts( $atts, $item, $args ) {
    if ( 7857 == $item['ID'] ) {
        // inspect $item, then …
        $atts['onclick'] = 'SnapEngage.startLink();';
        return $atts;
    }
}

However adding that if statement the one commenter suggested I get the following error:

Fatal error: Cannot use object of type WP_Post as array

I’m assuming more code is required but at a lost. As a reminder without the if statement it works however it targets all links rather than the one link I want to target.

Related posts

4 comments

  1. Specifically editing the code you provided in the original question:

    add_filter( 'nav_menu_link_attributes', 'wpse121123_contact_menu_atts', 10, 3 );
    function wpse121123_contact_menu_atts( $atts, $item, $args )
    {
      // The ID of the target menu item
      $menu_target = 123;
    
      // inspect $item
      if ($item->ID == $menu_target) {
        $atts['data-toggle'] = 'modal';
      }
      return $atts;
    }
    
  2. The second $item argument, which is being made available to your filter function, contains a menu item object. If dumped it looks something like this:

    [1] => WP_Post Object
        (
            [ID] => 2220
            [post_author] => 1
            [post_date] => 2012-12-26 19:29:44
            [post_date_gmt] => 2012-12-26 17:29:44
            [post_content] => 
            [post_title] => Home
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => open
            [ping_status] => open
            [post_password] => 
            [post_name] => home-3
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2013-06-05 01:55:20
            [post_modified_gmt] => 2013-06-04 22:55:20
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://dev.rarst.net/?p=2220
            [menu_order] => 1
            [post_type] => nav_menu_item
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
            [db_id] => 2220
            [menu_item_parent] => 0
            [object_id] => 2220
            [object] => custom
            [type] => custom
            [type_label] => Custom
            [title] => Home
            [url] => http://dev.rarst.net/
            [target] => 
            [attr_title] => 
            [description] => 
            [classes] => Array
                (
                    [0] => 
                    [1] => menu-item
                    [2] => menu-item-type-custom
                    [3] => menu-item-object-custom
                    [4] => current-menu-item
                    [5] => current_page_item
                    [6] => menu-item-home
                )
    
            [xfn] => 
            [current] => 1
            [current_item_ancestor] => 
            [current_item_parent] => 
        )
    

    To target specific menu item you need to formulate your condition and check it against data available in the object, for example if ( 2220 == $item['ID'] )

  3. Why don’t you approach this problem from a different direction? Rather than attempting to target the menu item with id == ?? which could change at some point (the menu item, not the id), use the WP Admin area to add a custom class to the menu item you want to target. Then use that class in your Javascript to trigger the information you need:

    $('.my-class').click(function(e){
      // do other stuff
      e.preventDefault;
    });
    

    My javascript is not guaranteed. If you’re not using jQuery, you could try this.

  4. I wanted to add data-letters to the custom menu that I had created in WordPress.

    The steps I chose was:

    1. Found my menu’s id number.
    2. added those lines of code from @guiniveretoo
    3. wrote if statements for each menu items (as I wanted different attribute values to be injected.)
    4. worked!

    Here is my code.

    add_filter( 'nav_menu_link_attributes', 'wpse121123_contact_menu_atts', 10, 3 );
    function wpse121123_contact_menu_atts( $atts, $item, $args )
    {  
      $menu_target = 6;
    
      if ($item->ID == $menu_target) {
        $atts['data-letters'] = 'PROJECTS';
      }
    
      elseif ($item->ID == 7) {
        $atts['data-letters'] = 'RESUME';
      }
      elseif ($item->ID == 8) {
        $atts['data-letters'] = 'ARTWORKS';
      }
      elseif ($item->ID == 9) {
        $atts['data-letters'] = 'HELLO!';
      }
      return $atts;
    }
    

    Hope this helps you.

Comments are closed.