phpwordpresswp-nav-walker

How to add class to last <li> in Wordpress navigation bar?


So I'm using a custom navwalker in wordpress, as shown below:

function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
    {
        $title = $item->title;
        $permalink = $item->url;

        $output .= "<li>";
        $output .= "<a href='$permalink'>$title</a>";
        }
    }

I just need to add the class .button to the last <li> in the list. Something like this:

if (not the last class) {
    $output .= "<li>";
    $output .= "<a href='$permalink'>$title</a>";
} else {
    $output .= "<li class = 'button'>";
    $output .= "<a href='$permalink'>$title</a>";
}

Anyone have an easy way to accomplish this? I can't just add the class in wp admin because the custom navwalker overrides it, and I don't really want to use some hacky solution when I'm sure there's something pretty elegant to solve this issue. Thanks in advance!


Solution

  • Before I can answer your original question, there is something missing from your example function which will help. The $item variable has a property called classes which contains an array of classes for the element. This should include any classes the user puts into the menu builder in admin (which solves one of the problems you mentioned, but not the original question).

    First, we need to add something like this

    function start_el(&$output, $item, $depth = 0, $args = null, $id = 0)
        {
            $title = $item->title;
            $permalink = $item->url;
            $classes = implode(" ", $item->classes);
    
            $output .= “<li classes=‘$classes’>”;
            $output .= "<a href='$permalink'>$title</a>";
            }
        }
    

    Now that you’ve added the missing classes, you can programmatically add a class to the element instead of having a user do it in admin by using a filter. This would probably go somewhere in your functions.php file.

    function custom_nav_classes ($items) {
        $items[count($items) - 1]->classes[] = 'last';
        return $items;
    }
    add_filter('wp_nav_menu_objects', 'wpb_first_and_last_menu_class');
    

    To explain, we added a WP Filter which will be called when the nav menu is being prepared for render. The filter used is for all menu objects, so the parameter we will receive is an array of all menu items. We used count to get the length of the array, and then subtracted one because arrays start at 0. This is how we find the last item. Then we appended a new classes to the classes property using classes[] (PHP shorthand for appending to an array).

    Side note You might have already done this, but it’s useful to ask yourself in this situation if you need this class or if you can use CSS/JavaScript selectors to accomplish what you need. I don’t know your use-case, but just some food for thought. For example ul.menu > li:last-child or something along those lines could be useful. Not technically part of the answer, just something worth mentioning.