A recent WordPress project required the ability to dynamically add custom post type categories to WordPress menus

The custom post type had a custom taxonomy called ‘categories’ and the design called for a drop down menu that could be populated with new categories when they are added in the dashboard to the custom post type.

There appear to be a few different approaches to this problem, ranging from filtering on wp_nav_menu_items to building a custom nav_walker but by far the cleanest and easiest method I found was from just another designer & developer. The trick was to modify the items_wrap argument that goes into wp_nav_menu allowing for some sort of control over the contents of the menu.

My dynamic menu needed to be second in the list as a dropdown. I used the marvellous Menuzord Responsive Megamenu from ThemeForest to style the menu and add responsiveness. Copy the two functions below into your theme’s functions.php. The nav_menu_css_class filter was needed to get the class of active into the currently selected menu item.

/*
 * 
 * add 'active' to current menu entries
 * 
 */

add_filter('nav_menu_css_class' , 'osi_active_nav_class' , 10 , 2);

function osi_active_nav_class ($classes, $item) {
    if (in_array('current-menu-item', $classes) ){
        $classes[] = 'active ';
    }
    return $classes;
}



/*
 * 
 * Custom menu wrap for adding toy categories
 * 
 */

function my_nav_wrap() {
    
    global $post;
    
    $items = '';
    
    $items .= '<li><a href="#">Toy Categories</a><ul class="dropdown">';
    
    $terms = get_terms( array(
        'taxonomy' => 'categories',
        'hide_empty' => false,
    ) );
    
    foreach ($terms as $term) {
        $items .= '<li><a href="' . get_term_link($term) . '">' . $term->name . '</a></li>';
    }
    
    $items .= '</ul></li>';

    $wrap  = '<ul id="%1$s" class="%2$s">';
    $wrap .= '<li><a href="http://toys.dev/" title="Home">Home</a></li>';
    $wrap .= $items;
    $wrap .= '%3$s';
    $wrap .= '</ul>';
    
    return $wrap;
}

Then, in your header.php template file, put the below call to wp_nav_menu. As you can see the items_wrap argument passed to wp_nav_menu is calling our custom function from above

<?php 

    wp_nav_menu(array(
        'theme_location'    => 'primary',
        'menu_class'        => 'menuzord-menu',
        'container'         => 'div',
        'container_class'   => 'menuzord',
        'container_id'      => 'menuzord',
        'items_wrap' => my_nav_wrap()
    )); 

?>

And finally, this is what the primary menu looks like within WordPress menu editor

wordpress-menus