Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

WordPress doesn't add parent class to menu items that have submenus. Therefore this is required to extend this:

function add_parent_css( $classes, $item ) {
    global $have_children;
    if( $have_children ) {
        $classes[] = 'parent';
    }
    return $classes;
}
add_filter( 'nav_menu_css_class', 'add_parent_css', 10, 2 );

class custom_walker extends Walker_Nav_Menu {
  function display_element($element, &$children_elements, $max_depth, $depth=0, $args, &$output){
    $GLOBALS['have_children'] = (isset($children_elements[$element->ID]))? 1:0;
    parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
  }
  [...]
}

The code will insert parent class to all menu items that have sub-menus and this can be then used in CSS like:

.parent:after { content: ">"; }

I'm wondering though, if there is a way to do that without custom menu walker? Just with filters? The reason I'm asking this is because some plugins like WPML ignore custom menu walkers for menu items and their "language switcher" in the menu doesn't get parent class even if has sub-items. Instead of waiting for WPML to fix that I would prefer to just update the menu in a theme to do it in a simpler way.

share|improve this question
    
Do you know which related function WPML uses? wp_list_pages, wp_nav_menu etc. –  TheDeadMedic Jun 26 '13 at 11:00
    
They add new items to wp_nav_menu but I would prefer to get rid of theme custom menu walker anyway. I would prefer it to have parent class via filter only. –  Paul Jun 26 '13 at 11:01
add comment

2 Answers 2

I'm using the following code to achieve this. Doesn't need any walkers or anything else, just insert this into your functions.php and the items with sub-menu will get "menu-parent-item" added as class.

add_filter( 'wp_nav_menu_objects', 'add_menu_parent_class' );
function add_menu_parent_class( $items ) {
    $parents = array();
    foreach ( $items as $item ) {
        //Check if the item is a parent item
        if ( $item->menu_item_parent && $item->menu_item_parent > 0 ) {
            $parents[] = $item->menu_item_parent;
        }
    }

    foreach ( $items as $item ) {
        if ( in_array( $item->ID, $parents ) ) {
            //Add "menu-parent-item" class to parents
            $item->classes[] = 'menu-parent-item'; 
        }
    }

    return $items;    
}

I've been using this for a long time. Unfortunately I can't remember where I found it, so can't give credits to the one who came up with it.

share|improve this answer
add comment
function wpse_104316_nav_menu_css_class( $classes, $item ) {
    if ( ! empty( $item->current_item_parent ) || ! empty( $item->current_item_ancestor ) ) 
        $classes[] = 'parent';
    return $classes;
}

add_filter( 'nav_menu_css_class', 'wpse_104316_nav_menu_css_class', 10, 2 );

Update: Seems you can't achieve it with the above approach. But you can however "force" the custom walker by hooking onto wp_nav_menu_args:

function wpse_104316_wp_nav_menu_args( $args ) {
    $args['walker'] = new custom_walker;
    return $args;
}

add_filter( 'wp_nav_menu_args', 'wpse_104316_wp_nav_menu_args', 100 );

Use this in addition to your current code.

share|improve this answer
    
It raises an error: FATAL ERROR: CANNOT USE OBJECT OF TYPE STDCLASS AS ARRAY IN ... –  Paul Jun 26 '13 at 11:12
    
Sorry, try update. –  TheDeadMedic Jun 26 '13 at 11:17
    
Both $item->current_item_parent and $item->current_item_ancestor have false for parent and children menu items when I'm viewing parent menu item so it doesn't add parent class to anything unfortunately. –  Paul Jun 26 '13 at 11:24
    
Check revision. –  TheDeadMedic Jun 26 '13 at 11:43
    
Thanks! This is a good solution to my issue but I'll go with something that doesn't require custom walker. If I may suggest something for anyone trying to do this: do it with jQuery. You'll save time and you'll maintain the code without custom walker which is usually better. WordPress is likely to update their code with "parent-menu-item" class that is added for items that have children: core.trac.wordpress.org/ticket/20191 Hopefully they will also add "description" support and ability to set custom "data-*" attributes or custom classes for more items than just parent wrapper or LI. –  Paul Jun 26 '13 at 13:10
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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