htmlwordpressmenuwp-nav-walker

Apply the navbar-dropdown class to just the first level of a menu


So I'm working on building a Navwalker for WordPress and I'm stuck on one step and I can't seem to figure out how to make this work.

So I have a menu with the dropdown which uses navbar-dropdown.

So I want the start_lvl to only be applied to the first dropdown but not the second or third levels.. how would I be able to apply the navbar-dropdown to just the first level of a menu dropdown?

So as shown in the picture, I want the first level to have the navbar-dropdown class (highlighted in green) but then all of the other ul levels to not have the navbar-dropdown.

Picture for reference: enter image description here

class Navwalker extends Walker_Nav_Menu {

    public function start_lvl( &$output, $depth = 0, $args = array() ) {
        $indent  = str_repeat( "\t", $depth );
        $output .= "\n$indent<ul role=\"menu\" class=\"navbar-dropdown\">\n";
    }

    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

        $custom_classes_from_menu = implode(' ', $item->classes); // turn the WP classes object array to string values

        $liClasses = 'navbar-item ' . $custom_classes_from_menu; // add the values to your classes list

        // If menu it has children
        $hasChildren = $args->walker->has_children;

        $liClasses .= $hasChildren ? " has-dropdown is-hoverable": "";

        if ($hasChildren) {
            $output .= "<li class='" . $liClasses . "'>";
            $output .= "\n<a class='navbar-link' href='" . $item->url . "'>" . $item->title . "</a>";
        }
        else {
            $output .= "<a class='" . $liClasses . "' href='" . $item->url . "'>" . $item->title;
        }

        // Adds has_children class to the item so end_el can determine if the current element has children
        if ($hasChildren) {
            $item->classes[] = 'has_children';
        }
    }

    public function end_el(&$output, $item, $depth = 0, $args = array(), $id = 0 ){

        if(in_array("has_children", $item->classes)) {

            $output .= "</li>";
        }
        $output .= "</a>";
    }

    public function end_lvl (&$output, $depth = 0, $args = array()) {

        $output .= "</ul>";
    }
}

Solution

  • Please change your start_lvl function to this:

    public function start_lvl( &$output, $depth = 0, $args = array() ) {
            $indent  = str_repeat( "\t", $depth );
            if($depth == 0)
                $output .= "\n$indent<ul role=\"menu\" class=\"navbar-dropdown\">\n";
            else
                $output .= "\n$indent<ul role=\"menu\">\n";
        }

    I hope this will be helpful.