Search code examples
javascriptphpwordpresswordpress-themingwordpress-rest-api

Wordpress Nav Walker - Multilevel navigation


I need help with navigation in Wordpress site. I'm trying to get Wordpress print my navigation in this format:

<ul data-menu="main" class="menu__level">
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-1" href="#">Vegetables</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-2" href="#">Fruits</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-3" href="#">Grains</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-4" href="#">Mylk & Drinks</a></li>
      </ul>
      
<!-- Submenu 1 / Shown when user clicks the first list item (item with data-submenu="submenu-1") on data-menu="main" -->
      <ul data-menu="submenu-1" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Stalk Vegetables</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Roots & Seeds</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Cabbages</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Salad Greens</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Mushrooms</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-1-1" href="#">Sale %</a></li>
      </ul>
      
<!-- Submenu 2 / Shown when user clicks the second list item (item with data-submenu="submenu-2") on data-menu="main" -->
      <ul data-menu="submenu-2" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Citrus Fruits</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Berries</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-2-1" href="#">Special Selection</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Tropical Fruits</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Melons</a></li>
      </ul>
      
<!-- Submenu 3 / Shown when user clicks the third list item (item with data-submenu="submenu-3") on data-menu="main" -->
      <ul data-menu="submenu-3" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Buckwheat</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Millet</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Quinoa</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Wild Rice</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Durum Wheat</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-3-1" href="#">Promo Packs</a></li>
      </ul>
      
<!-- Submenu 4 / Shown when user clicks the forth list item (item with data-submenu="submenu-4") on data-menu="main" -->
      <ul data-menu="submenu-4" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Grain Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Seed Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Nut Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Nutri Drinks</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-4-1" href="#">Selection</a></li>
      </ul>

But I can't figure out how to specify child items to specific parent item and then printing them with data-submenu.

Navigation structure is taken from here: http://tympanus.net/Blueprints/MultiLevelMenu/

Thanks!

Update: This crossed my mind: would it be easier or cleaner to just get navigation data with php and then populate it in right format with Javascript? Does anyone know if this would be better way to handle this?

Or how about using rest-api with this (I'm fairly new with this, so is there point to use it as a part of in small website project)


Solution

  • Actually, you can just grab all menu data (from certain location) into the array & output it any way you like.

    For example, you have menu structure like this:

    Menu_parent1_item
        Submenu_item_1
        Submenu_item_2
        Submenu_item_3
    Menu_parent2_item
        Submenu2_item_1
        Submenu2_item_2
        Submenu2_item_3
    Menu_parent3_item
        Submenu3_item_1
        Submenu3_item_2
        Submenu3_item_3
    

    Put this code inside function.php:

    function custom_menu_output( $theme_location ) {
        if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
            $menu = get_term( $locations[$theme_location], 'nav_menu' );
            $menu_items = wp_get_nav_menu_items($menu->term_id);
    
            $menus = array();
    
            foreach( $menu_items as $menu_item ) {
                $pid = $menu_item->menu_item_parent ? $menu_item->menu_item_parent : 0;
    
                $menus[$pid][] = array(
                    'link' => $menu_item->url,
                    'title' => $menu_item->title,
                    'id' => $menu_item->ID,
                );
            }
    
            foreach($menus as $key => $menu) {
                if($key == 0)
                    echo '<ul data-menu="main" class="menu__level">';
                else
                    echo '<ul data-menu="submenu-'.$key.'" class="menu__level">';
                foreach($menu as $item) {
                    if(isset($menus[$item['id']]))
                        echo '<li class="menu__item"><a class="menu__link" data-submenu="submenu-'.$item['id'].'" href="'.$item['link'].'">'.$item['title'].'</a></li>';
                    else
                        echo '<li class="menu__item"><a class="menu__link" href="'.$item['link'].'">'.$item['title'].'</a></li>';
                }
                echo '</ul>';
            }
    
        } else {
            $menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
        }
        echo $menu_list;
    }
    

    And use it like this in your template:

    <?php custom_menu_output('menu_location_name_from_register_nav_menu'); ?>
    

    It will generate HTML like this (I've based it on your question description):

    <ul data-menu="main" class="menu__level">
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-717" href="http://yourdomain.tld/your_link/">Menu_parent1_item</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-720" href="http://yourdomain.tld/your_link/">Menu_parent2_item</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-725" href="http://yourdomain.tld/your_link/">Menu_parent3_item</a></li>
    </ul>
    
    <ul data-menu="submenu-717" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_1</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_2</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_3</a></li>
    </ul>
    
    <ul data-menu="submenu-720" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_1</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_2</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_3</a></li>
    </ul>
    
    <ul data-menu="submenu-725" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_1</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_2</a></li>
        <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_3</a></li>
    </ul>
    

    You can further customize this code for your needs.