1

I integrate a template into Wordpress theme. But I have a trouble with the menu.
The menu come with class in <li> like <li class="nav-link"> if active <li class="nav-link active"> but I would like to <a class="nav-link"> if active <a class="nav-link active"> I used walker.

this is my menu actually:

<nav class="collapse">
<ul class="nav nav-pills" id="mainNav">
<li id="menu-item-14" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home menu-item-14 nav-link">
    <a href="http://mydom.com/">Accueil</a>
</li>
<li id="menu-item-85" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-85 nav-link">
    <a href="http://mydom.com/a-propos/">A propos</a>
</li>
<li id="menu-item-97" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-97 dropdown nav-link">
    <a href="http://mydom.com/blog/" data-toggle="dropdown" data-target="#" class="dropdown-toggle">Blog<b class="caret"></b>
    </a>
  <ul class="dropdown-menu">
      <li id="menu-item-98" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-98 nav-link">
      <a href="http://mydom.com/sample-page/">Sample Page</a>
      </li>
  </ul>
</li>
<li id="menu-item-79" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-77 current_page_item menu-item-79 nav-link nav-link active">
    <a href="http://mydom.com/contact/">Contact</a>
</li>
</ul>                               

Now I would like that appear like this:

<nav class="collapse">
<ul class="nav nav-pills" id="mainNav">
<li id="menu-item-14" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home menu-item-14">
    <a href="http://mydom.com/" class="nav-link">Accueil</a>
</li>
<li id="menu-item-85" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-85">
    <a href="http://mydom.com/a-propos/" class="nav-link">A propos</a>
</li>
<li id="menu-item-97" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-97 dropdown">
    <a href="http://mydom.com/blog/" data-toggle="dropdown" data-target="#" class="dropdown-toggle nav-link">Blog<b class="caret"></b></a>
  <ul class="dropdown-menu">
      <li id="menu-item-98" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-98">
      <a href="http://mydom.com/sample-page/" class="nav-link">Sample Page</a></li>
  </ul>
</li>
<li id="menu-item-79" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-77 current_page_item menu-item-79">
    <a href="http://mydom.com/contact/" class="nav-link active">Contact</a>
</li>
</ul>                               

I use this class walker and function :

class mydom_nav_walker extends Walker_Nav_Menu {    
function start_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul class=\"dropdown-menu\">\n";
}
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;
    if ($args->has_children && $depth > 0) {
        $classes[] = 'dropdown-submenu';
    } else if($args->has_children && $depth === 0) {
        $classes[] = 'dropdown';
    }
    $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 ) . '"' : '';

    $output .= $indent . '<li' . $id . $value . $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        ) .'"' : '';
    $attributes .= ($args->has_children)        ? ' data-toggle="dropdown" data-target="#" class="dropdown-toggle"' : '';

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

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

    if ( !$element )
        return;

    $id_field = $this->db_fields['id'];

    //display this element
    if ( is_array( $args[0] ) )
        $args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );
    else if ( is_object( $args[0] ) ) 
        $args[0]->has_children = ! empty( $children_elements[$element->$id_field] ); 
    $cb_args = array_merge( array(&$output, $element, $depth), $args);
    call_user_func_array(array($this, 'start_el'), $cb_args);

    $id = $element->$id_field;

    // descend only when the depth is right and there are childrens for this element
    if ( ($max_depth == 0 || $max_depth > $depth+1 ) && isset( $children_elements[$id]) ) {

        foreach( $children_elements[ $id ] as $child ){

            if ( !isset($newlevel) ) {
                $newlevel = true;
                //start the child delimiter
                $cb_args = array_merge( array(&$output, $depth), $args);
                call_user_func_array(array($this, 'start_lvl'), $cb_args);
            }
            $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
        }
        unset( $children_elements[ $id ] );
    }

    if ( isset($newlevel) && $newlevel ){
        //end the child delimiter
        $cb_args = array_merge( array(&$output, $depth), $args);
        call_user_func_array(array($this, 'end_lvl'), $cb_args);
    }
    //end this element
    $cb_args = array_merge( array(&$output, $element, $depth), $args);
    call_user_func_array(array($this, 'end_el'), $cb_args);
}
}

function webriti_nav_menu_css_class( $classes ) {
    $classes[]  =   'nav-link';
    if ( in_array('current-menu-item', $classes ) OR in_array( 'current-menu-ancestor', $classes ) )
        $classes[]  =   'nav-link active';

    return $classes;
}

add_filter( 'nav_menu_css_class', 'webriti_nav_menu_css_class' );

In my header I call my menu like this:

<nav class="collapse">
    <?php wp_nav_menu( array(
        'theme_location' => 'header-menu',
        'container'=>false,
        'walker' => new mydom_nav_walker(),                             
        'items_wrap' => '<ul class="nav nav-pills" id="mainNav">%3$s</ul>'
    ) ); ?>
</nav>

Thanks for help

0

If you use your custom Walker class, then there's no point in using filters for adding these classes.

Let's take a look at this part of your code:

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

$output .= $indent . '<li' . $id . $value . $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        ) .'"' : '';
$attributes .= ($args->has_children)        ? ' data-toggle="dropdown" data-target="#" class="dropdown-toggle"' : '';

$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';

In first line you call your filter, and then you use these classes in <li> element.

The last line of that fragment is responsible for displaying <a> element.

So here's that function with modifications (you don't need to use nav_menu_css_class filter anymore):

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;
    if ($args->has_children && $depth > 0) {
        $classes[] = 'dropdown-submenu';
    } else if($args->has_children && $depth === 0) {
        $classes[] = 'dropdown';
    }
    $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 ) . '"' : '';

    $output .= $indent . '<li' . $id . $value . $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        ) .'"' : '';
    $attributes .= ($args->has_children)        ? ' data-toggle="dropdown" data-target="#" class="dropdown-toggle"' : '';

    $a_classes = array('nav-link');
    if ( in_array('current-menu-item', $classes ) OR in_array( 'current-menu-ancestor', $classes ) ) {
        $a_classes[]  =   'active';
    }
    $attributes .= ( ! empty( $a_classes ) ) ? ' class="' . esc_attr( join( ' ', $a_classes) ) . '"' : '';

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

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
  • Thank you very much. It works perfectly! thanks again. – titimi Jul 30 '18 at 15:22

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.