1

I'm trying to add a custom menu structure for my WordPress theme. This is how I want it to look:

<li>
    <a href="link_to_parent_item" class="main-category" tabindex="3">Parent Name</a>
    <div class="sub-menu">
        <div class="sub-links pull-left">
            <a href="link_to_child_item">Child Name1</a>
            <a href="link_to_child_item">Child Name2</a>
        </div>
    </div>
</li>

I've written a custom walker to do this, but it is not giving me what I really want. Here's my walker class:

class loggmax_class_walker extends Walker_Nav_Menu{

// Start level, beginning tags
function start_lvl(&$output, $depth) {
    $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
    $output .= "\n$indent";
    $output .= '<div class="sub-menu">';
    $output .= '<div class="sub-links pull-left">';
}

function end_lvl(&$output, $depth) {
    $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
    $output .= "$indent</div>";
    $output .= '</div>';
}

// Start element (beginning list items)
function start_el( &$output, $item, $depth=0, $args=array(),$current_object_id=0 ) {
    $this->curItem = $item;
    $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 ) . '"' : '';
    $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
    $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

    $atts = array();
    $atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
    $atts['target'] = ! empty( $item->target )     ? $item->target     : '';
    $atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
    $atts['href']   = ! empty( $item->url )        ? $item->url        : '';
    $atts['slug']   = ! empty( $item->slug )        ? $item->slug      : '';
    $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
    $attributes = '';
    $item_output = '';
    foreach ( $atts as $attr => $value ) {
        if ( ! empty( $value ) ) {
            $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
            $attributes .= ' ' . $attr . '="' . $value . '"';
        }
    }

    // Check if it is a submenu
    if ( $depth == 1 ) {
        $output .= '<a'. $attributes. ' >';
        $output .= apply_filters( 'the_title', $item->title, $item->ID );
        $output .= '</a>';

    } elseif ( $depth == 0 ) {
        $item_output .= '<li>';
        $item_output .= '<a'. $attributes. ' class="main-category">';
        $item_output .= apply_filters( 'the_title', $item->title, $item->ID );
        $item_output .= '</a>';
    }

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

and this code is in my header.php

if ( has_nav_menu( 'primary-menu' ) )
        wp_nav_menu( array(
            'theme_location'    => 'primary-menu',
            'container'         => 'ul',
            'menu_class'        => 'pull-left',
            'items_wrap'        => '<ul id="%1$s" class="%2$s">%3$s</ul>',
            'walker'            => new loggmax_class_walker()
        ) );

and this is what is being displayed:

<li>
   <a href="link_here" class="main-category">Parent Title</a>
    <div class="sub-menu">
       <div class="sub-links pull-left">
         <a href="link_here">Child Title</a></li>
         <a href="link_here">Child Title 2</a></li>
    </div>
</li>

How do I remove the ending list tag </li> that is being printed in the sub-menu items?

1

It appears the

<li></li>

in the end_lvl function and also within $item_output as well. Although I have no experience with writing walker code, I have previously used a Bootstrap walker, so these might not be of any use to you. Perhaps taking a look through the following links might help?

  • Thanks for you answer. Going through some WordPress documentation, I've been able to update the walker class. But the ending list tag </li> is still being printed in the code, at the sub-menu level. Any ideas on this? – Samuel Asor Sep 22 '16 at 22:50
  • Where is the definition of $args? The only thing I can think of is your using $args->link_before and $args->link_after. I can't see where it is defined in the code. – EBennett Sep 25 '16 at 16:19
  • You're correct @EBennett. I've updated the code, but the ending list tag </li> is still being printed in sub-menu items. – Samuel Asor Sep 27 '16 at 7:22
0

Old question, but you can override the </li> in the Walker's end_el() function (see wp-includes/class-walker-nav-menu.php); in your case, something like:

public function end_el( &$output, $item, $depth = 0, $args = array() ) {
    if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
        $n = '';
    } else {
        $n = "\n";
    }
    if ( $depth == 0 ) {
        $output .= "</li>{$n}";
    } else {
        $output .= "{$n}";
    }
}
  • Please add CODE example to show how to do it. Only referring to WordPress core file is not enough as a good answer. – Fayaz Aug 21 '18 at 8:49
  • For somebody writing a custom Menu Walker (including start_el) that seems highly unnecessary to me—but there you go ;) – Valentin Born Aug 21 '18 at 9:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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