Search code examples
phpwordpresssubmenu

How can I add parent menu description to my Wordpress menu?


I've entered the description into the parent menu items in Wordpress, but they're not showing on my theme.

I know that a walker class can be used to make changes to the menu, but I don't know how to code it.

Here is what I want to achieve:

<nav id="main-menu" role="navigation">
<div class="menu-main-menu-container">
    <ul id="menu-main-menu" class="menu">
        <!-- REPEATING MENU ITEM START -->
        <li class="menu-parent-item"><a>Face</a>
        <ul class="sub-menu">
            <li class="menu-image-container">
                <div class="menu-image"></div>
                <div class="menu-description">[Face menu item description]</div>
            </li>
            <li class="heading">Face</li>
            <ul class="sub-menu">
                <li class="menu-item">Sub menu 1</li>
                <li class="menu-item">Sub menu 2</li>
                <li class="menu-item">Sub menu 3</li>
            </ul>
            <li class="heading">Ear</li>
            <ul class="sub-menu">
                <li class="menu-item">Sub menu 1</li>
                <li class="menu-item">Sub menu 2</li>
                <li class="menu-item">Sub menu 3</li>
            </ul>
            <li class="heading">Eyes</li>
            <ul class="sub-menu">
                <li class="menu-item">Sub menu 1</li>
                <li class="menu-item">Sub menu 2</li>
                <li class="menu-item">Sub menu 3</li>
            </ul>
        </ul>
        </li>
        <!-- REPEATING MENU ITEM END -->
    </ul>
</div>

As you can see, I only want the description of the parent menu item to be shown, but it needs to be within the first ul.sub-menu within the parent list item.

How could I code a walker that uses start_lvl, start_el and end_lvl to handle this efficiently?


Solution

  • I managed to get the menu to display as before, whilst adding the parent menu description exactly where I wanted by simply just adding to what I already had.

    I already had a walker that created the sub-menu image container, and the description container

    // Submenu walker to add image
    class submenu_walker extends Walker_Nav_Menu {
        function start_lvl( &$output, $depth = 0, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            $output .= "\n$indent<ul class='sub-menu'><li class='menu-image-container'><div class='menu-image'></div><div class='menu-description'></div></li>\n";
        }
        function end_lvl( &$output, $depth = 0, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            $output .= "$indent<li><div class='clear'></div></li></ul>\n";
        }
    }
    

    Then I managed to find a function that uses start_el and could assign the description to a variable, but not output it, then just output the $item_output as normal.

    function add_menu_description( $item_output, $item, $depth, $args ) {
        $description = __( $item->post_content );
        return $item_output;
    }
    add_filter( 'walker_nav_menu_start_el', 'add_menu_description', 10, 4);
    

    Of course now I needed to use $description within my other submenu walker function, so I just created a global variable in both, and the output is exactly what I'm after!

    FINAL OUTPUT

    function add_menu_description( $item_output, $item, $depth, $args ) {
        global $description;
        $description = __( $item->post_content );
        return $item_output;
    }
    add_filter( 'walker_nav_menu_start_el', 'add_menu_description', 10, 4);
    
    // Submenu walker to add image
    class submenu_walker extends Walker_Nav_Menu {
        function start_lvl( &$output, $depth = 0, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            global $description;
            $output .= "\n$indent<ul class='sub-menu'><li class='menu-image-container'><div class='menu-image'></div><div class='menu-description'>".$description."</div></li>\n";
        }
        function end_lvl( &$output, $depth = 0, $args = array() ) {
            $indent = str_repeat("\t", $depth);
            $output .= "$indent<li><div class='clear'></div></li></ul>\n";
        }
    }