1

I need your help, am trying to add class dropdown-submenu to a <li> element which has children. Not sure if I was clear enough, so here is an example:

   |-Home (Parent Item)
   |-Services (Parent Item) *class='dropdown'*
       |-Orthodontics (Child Item) *** class="dropdown-submenu" ***
          |-Invisalign (Sub Child Item)
          |-Inman Aligner (Sub Child Item)

The HTML format is:

                        <!-- Services -->
                <li class="dropdown active">
                <a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown">
                        Services
                    </a>
                    <ul class="dropdown-menu">
                        <!-- Service Orthodontics -->
                        <li class="dropdown-submenu active">
                            <a href="javascript:void(0);">Orthodontics</a>
                            <ul class="dropdown-menu">
                                <li><a href="invisalign.html">Invisalign</a></li>
                                <li><a href="inman_aligner.html">Inman Aligner</a></li>
                            </ul>
                        </li>
                        <!-- End Service Orthodontics -->

My walker-class gives all <li> elements which has <ul> class dropdown. It simply look if the element has child and if true it set the class name to dropdown. Here is the code of walker.php

        class Main_Walker_Nav_Menu extends Walker_Nav_Menu {

function start_lvl( &$output, $depth ){ //ul
    $indent = str_repeat("\t",$depth);
    $submenu = ($depth > 0) ? ' dropdown-menu' : '';
    $output .= "\n$indent<ul class=\"dropdown-menu$submenu depth_$depth\">\n";  }


function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ){ //li a span

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

    $li_attributes = '';
    $class_names = $value = '';

    $classes = empty( $item->classes ) ? array() : (array) $item->classes;

    $classes[] = ($args->walker->has_children) ? 'dropdown' : '';
    $classes[] = ($item->current || $item->current_item_anchestor) ? 'active' : '';
    $classes[] = 'menu-item-' . $item->ID;
    if( $depth && $args->walker->has_children ){
        $classes[] = 'dropdown-submenu';
    }

    $class_names =  join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args ) );
    $class_names = ' class="' . esc_attr($class_names) . '"';

    $id = apply_filters('nav_menu_item_id', 'menu-item-'.$item->ID, $item, $args);
    $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

    $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>';

    $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) . '"' : '';

    $attributes .= ( $args->walker->has_children ) ? ' class="dropdown-toggle" data-toggle="dropdown"' : '';

    $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 .= ( $depth == 0 && $args->walker->has_children ) ? '</a>' : '</a>';
    $item_output .= $args->after;

    $output .= apply_filters ( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

}

Thanks in advance.

3 Answers 3

0

I have not tested this but it looks like you aren't testing for $depth the way you need to be.

This block:

$classes[] = ($args->walker->has_children) ? 'dropdown' : '';
$classes[] = ($item->current || $item->current_item_anchestor) ? 'active' : '';
$classes[] = 'menu-item-' . $item->ID;
if( $depth && $args->walker->has_children ){
    $classes[] = 'dropdown-submenu';
}

Should be something like:

if ($args->walker->has_children) {
  if (0 === $depth) {
    $classes[] = 'dropdown';
  } else {
    $classes[] = 'dropdown-submenu';
  }
} 
$classes[] = ($item->current || $item->current_item_anchestor) ? 'active' : '';
$classes[] = 'menu-item-' . $item->ID;
0
0

when we say $args->walker->has_children means $depth == 1 you can add dropdown-submenu as below

if( $depth == 1 ){
    $classes[] = 'dropdown-submenu';
}
1
  • Yaah! It seems I wasn't testing the depth correctly Jan 4, 2016 at 17:06
0

I think you should try the nav_menu_submenu_css_class filter. This worked for me and it's really simple.

add_filter('nav_menu_submenu_css_class','some_function', 10, 3 );
function some_function( $classes, $args, $depth ){

    foreach ( $classes as $key => $class ) {
        if ( $class == 'sub-menu' && $depth == 0) {
            $classes[ $key ] = 'your-class';
        }elseif($class == 'sub-menu' && $depth == 1){
            $classes[ $key ] = 'your-class';
        }
    } 
    return $classes;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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