Nuance in adding CPT and TAX to a submenu

I have a lot of CPT’s and custom TAXs and decided to put them into a few submenus. That worked just fine. I’ll explain how I did that in a moment but the problem is that when you choose a “new term” or a “new post” the Admin’s sidebar menu loses track of being within a submenu and collapses the menu. This doesn’t strictly matter as you can add the item and then reopen the admin menu but it’s an irritant that I’d like to remove.

To help explain my problem, I’ve included a few screen shots. Here’s the Admin menu when I open it to my menu/submenu of “LG RefData / UOM”:

Read More

enter image description here

So far, all good. BTW, UOM is a a CPT (not a TAX). Now if I click on the “Add New” button at the top of the edit.php page then it brings up the page fine but the Admin menu collapses to look like this:

enter image description here

So that’s the main problem but there is a small corollary which is related to how TAX’s behave. In the original screen shot you saw a submenu called “UOM Context” which is a taxonomy. By default clicking on that immediately collapses the Admin menu but I have found a way around that (more on that in a sec) but my solution still leaves the menu looking like this when I click on the “UOM Context” link:

enter image description here

Notice that while it’s not collapsed it is not highlighting (aka, boldfacing) the submenu choice.

So let me show you the code I used to set this up (although it is likely fairly standard code for people trying to do this). The first thing that happens from an execution perspective is the CPT’s and TAX’s are registered. The trick with the CPT’s is to use the “show_in_menu” and set it to name of the menu page it will sit under:

        // Default args
        array(
            'label'                 => $plural,
            'labels'                => $labels,
            'public'                => true,
            'show_ui'               => $this->show_menu,
            'show_in_menu'          => $this->show_in_menu,
            'supports'              => array( 'title', 'editor' , 'excerpt'),
            'show_in_nav_menus'     => true,
            'menu_icon'             => LG_FE_DIR . "/img/lg-admin.png",
            'menu_position'         => $this->get_menu_priority(),
            '_builtin'              => false,
        ),

Note that this is not necessary for TAX’s and in my experimenting it seems to have no effect so I have just left it off. The second step is the add_menu_page and add_submenu_page calls:

add_menu_page ("LG Ref Data", "LG Ref Data", "manage_options", LG_REFDATA_MENU, "LG_AdminMenuSystem::show_reference_menu", plugins_url ("/img/LG.png", __DIR__), 61.1);
add_submenu_page (LG_REFDATA_MENU,"UOMs","UOMs","manage_options",'edit.php?post_type=uoms');
add_submenu_page (LG_REFDATA_MENU,"UOM Context","UOM Context","manage_options",'edit-tags.php?taxonomy=uom-contexts&post_type=uoms');
array_push (self::$tax_correct, "uom-contexts");    

Pretty standard stuff with the exception of the last line which is the beginning of my TAX Fix that I mentioned earlier (aka, stops the menu from collapsing when choosing a TAX item but doesn’t stop it when adding a new item). Here’s the actual code for the fix:

static public function tax_menu_correction ($parent_file) {
    global $current_screen;
    $taxonomy = $current_screen->taxonomy;
    if ( in_array($taxonomy,self::$tax_correct) )
        $parent_file = LG_REFDATA_MENU;
    return $parent_file;
}

which is then called from the following hook:

add_action( 'parent_file' , 'LG_AdminMenuSystem::tax_menu_correction'); // helps to keep the menu selection on the menu when choosing a custom TAX 

So that’s it. Any and all help would be greatly appreciated.

Related posts

Leave a Reply

3 comments

  1. I’ve answered a similar Question. AFAIK, you have to solve it with jQuery.

    var reference = $('#my-draft-posts').parent().parent();
    
    // add highlighting to our custom submenu
    reference.addClass('current');
    
    //remove higlighting from the default menu
    reference.parent().find('li:first').removeClass('current');
    

    And the trick is to add an ID in your custom menus, so you can reference them.

    add_submenu_page(
        'edit.php',
        'Drafts', 
        '<span id="my-draft-posts">Drafts</span>', // <---- HERE
        'edit_pages', 
        'edit.php?post_status=draft&post_type=post'
    );
    

    Much probably, you’ll need more jQuery than this sample.

  2. I’ve had a crack at it now, since I have a plugin that needs it. I also use the admin filter hook parent_file that lets you specify the top-level admin menu item under which your page logically sits. (NB: it’s a filter, not an action; add_action happens to work too, but it should really be add_filter)

    My problem is that I don’t actually want the custom post type edit page listed in a menu, I just want to link to it from another page that is in the menu. This means that I have 'show_in_menu' => false which I think is what you said you now have too.

    To get the submenu item set as ‘current’ I had to add in a side effect that changes a global variable $submenu_file to match the page on which I have that link.

    NB: this is nearly an exact rip from some working code, so please adjust to suit your code.

    // this filter only added when loading the edit page
    add_filter('parent_file', 'wpse_71865_filterParentFile');
    
    /**
    * tell WordPress admin the parent page for the menu
    * @param string $parent_file
    * @return string
    */
    public function wpse_71865_filterParentFile($parent_file) {
        global $submenu_file;
    
        // set parent menu item for filter return
        // (Gravity Forms in my case)
        $parent_file = 'gf_edit_forms';
    
        // set submenu item by side effect, link isn't in menu
        $submenu_file = 'gfdpspxpay-options';
    
        return $parent_file;
    }
    

    Note that I’m attaching to a page (i.e. page=gfdpspxpay-options) so $submenu_file might not work for you. If not, then take a look at wp-admin/menu-header.php which is where this all happens. There’s an array $submenu_items that is looped over to get build the submenu, and that’s where all the action takes place.

    edit: I reckon for your problem, you just need to set:

    $submenu_file = 'post-new.php?post_type=uoms'
    
  3. Hmmm. I don’t know what happened here. I could have sworn I’d already answered this question and closed it. In any event I used an approach based off of @brasofilo’s suggestion. Basically here’s all you need to do:

    In your PHP where you’re registering the submenu use a declaration like this:

    add_submenu_page ( LG_TRANSACTIONAL_MENU,
            $plural ,"<span id='submenu-{$plural}'>" . $plural . "</span>",
            "manage_options",
            "edit.php?post_type={$this->custom_type_slug_name}"
    );
    

    In my case this PHP resides in a custom-post-type plugin I’ve written so the variable names are particular to that but the key part is just that you’ve adding a DOM ID that your jQuery can select on. In this case the ID will be submenu-[plural name of CPT].

    The rest is done with jQuery:

    // If on a custom taxonomy editing page then make sure the menu item is selected
    if ( adminpage === "edit-tags-php") {
        $('#submenu-' + pagenow).closest('li').addClass('current');
    }
    // if on a edit post-type page (post-new.php) then make sure menu is selected, expanded, and the submenu is current
    if (adminpage === "post-new-php") {
        $('#submenu-edit-' + pagenow).closest('li').addClass('current');
        $('#submenu-edit-' + pagenow).closest('.wp-has-submenu').removeClass('wp-not-current-submenu').addClass('wp-has-current-submenu');
    }