Use wp_nav_menu to dynamically generate child menus

My solution uses the Walker_Nav_Menu and a custom class and is mostly hacked together from this post: How do I dynamically populate wp_nav_menu from a custom taxonomy?

Solution:

//define the custom post type
//could use "page" or "post" as well.
define("MENU_CPT", "action");

//custom function for selecting posts based on a page parent (ne' term_id)
function hgs_get_children_by_id($parent_id, $post_type=MENU_CPT) {
    $args = array(
        'posts_per_page' => -1,
        'post_type' => $post_type,
        'post_parent' => $parent_id,
        'orderby' => 'menu_order title',
        'order'  => 'DESC'
    );                  
    return get_posts( $args );
}

//custom nav menu walker class for Take Action Dropdown
class HGS_Walker_Nav_Menu extends Walker_Nav_Menu {
    /**
     * Display array of elements hierarchically.
     *
     * It is a generic function which does not assume any existing order of
     * elements. max_depth = -1 means flatly display every element. max_depth =
     * 0 means display all levels. max_depth > 0  specifies the number of
     * display levels.
     *
     * @since 2.1.0
     *
     * @param array $elements
     * @param int $max_depth
     * @return string
     */
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output="";

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field ) 
            {
            //var_dump($e); //for troubleshooting
                $top_level_elements[] = $e;
                if ( $e->type=='post_type' && $e->object == MENU_CPT ) {

                    $child_posts = hgs_get_children_by_id($e->object_id);

                    foreach ( $child_posts as $child ) {                      
                        $child = wp_setup_nav_menu_item($child);
                        $child->post_type="nav_menu_item";
                        $child->menu_item_parent = $e->$id_field;
                        $child->object="custom";
                        $child->type="custom";
                        $child->ID = $e->$id_field.$child->ID;
                        $children_elements[ $e->$id_field ][] = $child; 
                        $children_elements_classes[] = $child; 
                    }
                }
            }
            else
            {
                $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                {
                    $top_level_elements[] = $e;
                    if ( $e->type=='post_type' && $e->object == MENU_CPT ) {

                        $child_posts = hgs_get_children_by_id($e->object_id);

                        foreach ( $child_posts as $child ) {                      
                            $child = wp_setup_nav_menu_item($child);
                            $child->post_type="nav_menu_item";
                            $child->menu_item_parent = $e->$id_field;
                            $child->object="custom";
                            $child->type="custom";
                            $child->ID = $e->$id_field.$child->ID;
                            $children_elements[ $e->$id_field ][] = $child;
                            $children_elements_classes[] = $child; 
                        }
                    }
                }
                else
                {
                    $children_elements[ $e->$parent_field ][] = $e;
                }
            }
        }

        //assing the classes to our dynamically populated posts
        if ( $children_elements_classes )
            _wp_menu_item_classes_by_context($children_elements_classes);

        foreach ( $top_level_elements as $e )
            $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }

         return $output;
    }
}

We implement the menu like so:

<?php wp_nav_menu( array(
                        'theme_location'  => 'nav-right',
                        'menu'            => 'Right Navigation Column',
                        'container'       => 'div',
                        'container_class' => 'nav-inner',
                        'container_id'    => '',
                        'menu_class'      => 'menu',
                        'menu_id'         => '',
                        'echo'            => true,
                        'items_wrap'      => '<h2>Take Action</h2><ul class="%2$s">%3$s</ul>',
                        **'walker'        => new HGS_Walker_Nav_Menu**
                    ) ); ?>

So I hope this helps someone. It is certainly very customizable if you are using various post types in a single menu as well by running a condition on $e->type and $e->object.

If anyone has more insight or some thoughts on how to improve this, please share.