0

I'm currently trying to setup a custom nav walker that will use container_class from the menu as a prefix for the class names of the list items and children.

$defaults = array(
'menu'            => '',
'menu_class'      => '',
'menu_id'     => '',
'container'       => 'nav',
'container_class' => 'nav-primary',
'container_id'    => '',
'before'      => '',
'after'       => '',
'link_before'     => '',
'link_after'      => '',
'depth'       => 0,
'walker'          => new Custom_Nav_Walker(),
'theme_location'  => 'primary',
'items_wrap'      => '<ul>%3$s</ul>',
);
wp_nav_menu( $defaults );

The general idea is the walker will loop out the classes according to the container class name. Like so.

<nav class="nav-primary">
  <li class="nav-primary__item"><a href="#">Link</a></li>
  <li class="nav-primary__item"><a href="#">Link</a></li>
  <li class="nav-primary__item"><a href="#">Link</a></li>
</nav>

Hopefully someone can help.

0

2 Answers 2

1

Go with a custom Walker

class Your_Walker_Nav_Menu extends Walker_Nav_Menu {
    var $container_class;
    public function __construct($container_class) {
        $this->container_class = $container_class;
    }

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
        global $wp_query;
        $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent

        // Depth-dependent classes.
        $depth_classes = array(
            ( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
            ( $depth >=2 ? 'sub-sub-menu-item' : '' ),
            ( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
            'menu-item-depth-' . $depth
        );
        $depth_class_names = esc_attr( implode( ' ', $depth_classes ) );

        // Passed classes.
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );

        // Build HTML.
        $output .= $indent . '<li id="nav-menu-item-'. $item->ID . '" class="'. $this->container_class . '__item ' . $depth_class_names . ' ' . $class_names . '">';

        // Link 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 .= ' class="menu-link ' . ( $depth > 0 ? 'sub-menu-link' : 'main-menu-link' ) . '"';

        // Build HTML output and pass through the proper filter.
        $item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
            $args->before,
            $attributes,
            $args->link_before,
            apply_filters( 'the_title', $item->title, $item->ID ),
            $args->link_after,
            $args->after
        );
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

Notice the construct function, then when you call the menu:

'container_class' => 'nav-primary',
'walker' => new Your_Walker_Nav_Menu('nav-primary')
3
  • Tried your suggestion. it loops out container_class__item and not the value of the container_class.
    – 550
    Apr 16, 2016 at 21:03
  • Sorry, I didn't give you an explanation. The 'container_class' you pass in Your_Walker_Nav_Menu is just a string. It's mean that you can pass your container_class to Walker. I edited my answer for more clear.
    – Tung Du
    Apr 16, 2016 at 21:07
  • Cheers. Works perfect
    – 550
    Apr 16, 2016 at 21:13
0

So far i've tried pulling the value from the nav template.

https://github.com/WordPress/WordPress/blob/master/wp-includes/nav-menu-template.php.

I know it's related to
$class = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-'. $menu->slug .'-container"'; on line 353.

The value returns null when requesting it. The idea is to loop the value out as part of the class name. As I only need to return the name itself.

'primary-menu__item'

would become

$container_class . '-menu__item

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.