Tell me more ×
WordPress Answers is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am trying to determine if an item has a sub-item with depth 1 or higher. I cannot find anywhere if there is some function/query I can write that grabs the current item looks in the database if it has any sub-pages and returns true.

What I aim to do with this is give the <li> class a different class depending on the fact if the menu item has a sub-item.

The snippet out of the code for what i have so far:

if ($depth == 0) 
{
    if( /*page has subpages*/ )
    {
            $class_names = $class_names ? ' class="menu-enable"' : '';
    }
    else
    {
            $class_names = $class_names ? '' : '';
    }
}
else
{
    $class_names = $class_names ? ' class="sub-menu-enable"' : '';
}

Now I need some code that runs at page has sub-pages. How can I detect parent items?

Edit:

Full custom walker class now:

 class header_walker extends Walker_Nav_Menu
{
 /**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function start_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n</li>$indent<div class=\"menu-items\"><div class=\"submenu-item\"><ul>\n";
}

/**
 * @see Walker::end_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function end_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul></div></div>\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Menu item data object.
 * @param int $depth Depth of menu item. Used for padding.
 * @param int $current_page Menu item ID.
 * @param object $args
 */
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

    $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

    $class_names = $value = '';
    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $classes[] = 'menu-item-' . $item->ID;

    $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
    $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
            /*
    // values of depth
    echo $item->title.' - ';
    echo $depth.'<br />';
    echo $class_names;

    if ($depth == 0) 
    {
        if( check for subpage )
        {
            $class_names = $class_names ? ' class="menu-enable"' : '';
        }
        else
        {
            $class_names = $class_names ? '' : '';
        }
    }
    else
    {
        $class_names = $class_names ? ' class="sub-menu-enable"' : '';
    }*/

    $output .= $indent . '<li' . $class_names .'>';

    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
    $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

    $item_output = $args->before;
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
    $item_output .= '</a>';
    $item_output .= $args->after;

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
/**
 * @see Walker::end_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Page data object. Not used.
 * @param int $depth Depth of page. Not Used.
 */
function end_el( &$output, $item, $depth = 0, $args = array() ) {
    $output .= "</li>\n";
}

}

share|improve this question

1 Answer

up vote 0 down vote accepted

You can filter wp_nav_menu_objects and add the classes in one rush. You don’t even need a custom walker for that.

add_filter( 'wp_nav_menu_objects', 'add_has_children_to_nav_items' );

function add_has_children_to_nav_items( $items )
{
    $parents = wp_list_pluck( $items, 'menu_item_parent');
    $out     = array ();

    foreach ( $items as $item )
    {
        in_array( $item->ID, $parents ) && $item->classes[] = 'has-children';
        $out[] = $item;
    }
    return $items;
}

The class has-children will now be assigned to the matching li elements automatically.

In a custom walker you will find the class in $item->classes in your function start_el(). The following lines from the default walker will do the trick:

$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
share|improve this answer
Would this also work in a custom walker? since the custom walker is for a different thing entirely (heavily modifying the default sytem to include a hidden div below each <li> .. </li>). Or would i just use the above code next to the custom walker class? – Schippie Jan 8 at 9:34
@user25722 See my update. If you are using $item->classes somewhere you will get has-children. – toscho Jan 8 at 9:38
Tried the default code, even with the default nav menu walker but the only thing i get is in the ul (with the default) a class of childeren. No where does it add to the above list element a class of has-childeren for some reason :/ will add the current code to the the original post. – Schippie Jan 8 at 9:52
I tested my code with Twenty Eleven. It works. Are you sure you put the complete code into your theme’s functions.php? – toscho Jan 8 at 10:00
Yes though i used twentytwelve as base from which i started not eleven. :/ – Schippie Jan 8 at 10:02
show 2 more comments

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.