0

I am having some troubles with my wordpress walker code. I know it's possible to add a custom css class manually via the admin menu section. But what i am trying to achieve is to get this done automatically whenever a submenu page is added by my client.

The first step i took was to replace the ul li navigation and change it to an a href navigational style. This works. Now i am looking for a way to add a class to the submenu a href items...

This is how my walker looks like at the moment.

class Description_Walker extends Walker_Nav_Menu { function start_el(&$output, $item, $depth, $args) { $classes = empty($item->classes) ? array () : (array) $item->classes; $class_names = join(' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ); !empty ( $class_names ) and $class_names = ' class="'. esc_attr( $class_names ) . '"'; $output .= ""; $attributes = ''; !empty( $item->attr_title ) and $attributes .= ' title="' . esc_attr( $item->attr_title ) .'"'; !empty( $item->target ) and $attributes .= ' target="' . esc_attr( $item->target ) .'"'; !empty( $item->xfn ) and $attributes .= ' rel="' . esc_attr( $item->xfn ) .'"'; !empty( $item->url ) and $attributes .= ' href="' . esc_attr( $item->url ) .'"'; $title = apply_filters( 'the_title', $item->title, $item->ID ); $item_output = $args->before . "" . $args->link_before . $title . '' . $args->link_after . $args->after;

            if (array_search('menu-item-has-children', $item->classes)) {
            $output .= sprintf("\n<div data-delay='0' class='w-dropdown'><div class='dropdown-toggle'><div class='icon icon-dropdown-toggle'></div><div>$title</div></div>
            \n", ( array_search('current-menu-item', $item->classes) || array_search('current-page-parent', $item->classes) ) ? 'active' : '', $item->url,
             $item->title);
        } else {

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

    function start_lvl(&$output, $depth, $args ) {
            $indent = str_repeat("\t", $depth);
            $output .= "\n$indent<nav class=\"dropdown-list\">\n<div class=\"submenu_speech\"></div>";
    }

    function end_lvl( &$output, $depth, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            $output .= "$indent</nav></div>\n";
    }

    function end_el(&$output, $item, $depth, $args) {
            $output .= "\n";
    }

}

2 Answers 2

0

There are special filters for adding classes to the ul, li, or a tags in a menu.

For the a tags you want to use nav_menu_link_attributes. This allows you to modify all attributes on the a tag, so here's an example:

function my_nav_menu_link_attributes( $atts, $item, $args ) {
    if ( 'main' === $args->theme_location ) {
        if ( '0' === $item->menu_item_parent ) {
            $atts['class'] = 'top-level-item';
        } 
    }
    return $atts;
}
add_filter( 'nav_menu_link_attributes', 'my_nav_menu_link_attributes', 10, 3 );
2
  • hmm, this should work indeed. But nothing happens. No error, but the class isn't added to any a tag...
    – Danny
    Apr 19, 2019 at 15:26
  • Can you add the version of my code you're using to your question? Apr 19, 2019 at 15:47
0


class Description_Walker extends Walker_Nav_Menu
{
    function start_el(&$output, $item, $depth, $args)
    {
        $classes = empty($item->classes) ? array () : (array) $item->classes;

    if( $depth == 1 ){
      $class_names = join(' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
      !empty ( $class_names ) and $class_names = ' class="dropdown-link w-dropdown-link '. esc_attr( $class_names ) . '"';
    } else {
      $class_names = join(' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
      !empty ( $class_names ) and $class_names = ' class="'. esc_attr( $class_names ) . '"';
    }

    $output .= "";
    $attributes  = '';
    !empty( $item->attr_title ) and $attributes .= ' title="'  . esc_attr( $item->attr_title ) .'"';
    !empty( $item->target ) and $attributes .= ' target="' . esc_attr( $item->target     ) .'"';
    !empty( $item->xfn ) and $attributes .= ' rel="'    . esc_attr( $item->xfn        ) .'"';
    !empty( $item->url ) and $attributes .= ' href="'   . esc_attr( $item->url        ) .'"';
    $title = apply_filters( 'the_title', $item->title, $item->ID );
    $item_output = $args->before
    . "<a $attributes $class_names>"
    . $args->link_before
    . $title
    . '</a>'
    . $args->link_after
    . $args->after;

            if (array_search('menu-item-has-children', $item->classes)) {
            $output .= sprintf("\n<div data-delay='0' class='w-dropdown'><div class='dropdown-toggle w-dropdown-toggle'><div class='icon w-icon-dropdown-toggle'></div><div>$title</div></div>
            \n", ( array_search('current-menu-item', $item->classes) || array_search('current-page-parent', $item->classes) ) ? 'active' : '', $item->url,
             $item->title);
        } else {

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

    function start_lvl(&$output, $depth, $args ) {
            $indent = str_repeat("\t", $depth);
            $output .= "\n$indent<nav class=\"dropdown-list w-dropdown-list\">\n<div class=\"submenu_speech\"></div>";
    }

    function end_lvl( &$output, $depth, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            $output .= "$indent</nav></div>\n";
    }

    function end_el(&$output, $item, $depth, $args) {
            $output .= "\n";
    }

}

So when $depth==1 class 'dropdown-link w-dropdown-link' is added to the a tag.

It works, but is this a legit solution?

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.