10

I have a custom post type, Jobs, with 3 taxonomies under it in the Admin menu.

One of the taxonomies is Status, which is either Active or Closed. I want a menu item under Jobs for Active Jobs. I created it with this code

add_submenu_page(
    'edit.php?post_type=jobs',
    'Active Jobs',
    'Active Jobs',
    'manage_options',
    'edit.php?post_type=jobs&jobstatus=67'
);

This works perfectly, except that the Jobs menu item remains highlighted when the Active Jobs menu option is active. See screen shot

example of submenu display

I read in this article Current class on admin menu using add_submenu_page() to not include the parent slug as the first parameter. I don't know how to get the submenu to appear in the correct nav section when I remove the filename slug.

At this point I am not using a callback function, I am simply executing the same URL as the default Jobs submenu option, except with query params that filter the posts displayed. If moving this into a callback function will resolve the issue, I can do that. But I don't know what should go in the callback function. I want to display the standard custom post type edit page, just with a taxonomy filter in place. thanks for assistance

3
  • I'd be interested to know what solutions come up for this, since it seems quite difficult to do. The 'WordPress' way would be to add a drop-down filter menu as shown in your screenshot. Commented Mar 3, 2012 at 12:43
  • You have a mistake in the url 'edit.php?&post_type=jobs&jobstatus=67' ... that first & shouldn't be there, following the ?..
    – t31os
    Commented Mar 4, 2012 at 10:44
  • Mark - you are correct, and I have changed that in the code in the post above and on the live site. However that doesn't resolve the issue. Thank you for pointing that out.
    – stvwlf
    Commented Mar 4, 2012 at 10:53

4 Answers 4

6

Here is a solution I just came up with which doesn't use jQuery:

There is a filter parent_file in wp-admin/menu-header.php which runs right before outputting the menu. The inline comment says:

For plugins to move submenu tabs around.

It is just a filter on the global variable $parent_file and I am not sure what it does but we will use this filter to alter the global variable $submenu_file instead, which set the highlighted submenu. So this will be the solution in your case:

add_filter('parent_file', 'wpse44270_parent_file');

function wpse44270_parent_file($parent_file){
    global $submenu_file;
    if (isset($_GET['jobstatus']) && $_GET['jobstatus'] == 67) $submenu_file = 'edit.php?post_type=jobs&jobstatus=67';

    return $parent_file;
}

You may adapt this with any url formatting. For example I use the format admin.php?page=my_plugin_slug&action=myaction for my plugins' sub menus so I used this to highlight my sub menus:

add_filter('parent_file', 'wpse44270_1_parent_file');

function wpse44270_1_parent_file($parent_file){
    global $submenu_file;
    if (isset($_GET['page']) && isset($_GET['action'])) $submenu_file = $_GET['page'] . '&action=' . $_GET['action'];

    return $parent_file;
}

PS: I also tried the action admin_menu to set $submenu_file, and it did work in my case (custom plugin page/slug) but not for edit.php sub menus (your case). So I searched for another action/filter that runs later and it was the filter parent_file.

5

I made this work using the Posts menus and the Draft status. It relies on jQuery to modify the list item classes. Adapt to work with your post type and URLs.

This is the result:
extra drafts submenu item

add_action( 'admin_menu', 'wpse_44270_menu_admin' );
add_action( 'admin_head-edit.php', 'wpse_44270_highlight_menu_item' );

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

function wpse_44270_highlight_menu_item()
{
    global $current_screen;

    // Not our post type, exit earlier
    if( 'post' != $current_screen->post_type )
        return;

    if( isset( $_GET['post_status'] ) && 'draft' == $_GET['post_status'] )
    {       
        ?>
        <script type="text/javascript">
            jQuery(document).ready( function($) 
            {
                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');             
            });     
        </script>
        <?php
    }
}
2

i found out that you also need to use html entities for your link. since you have

add_submenu_page(
    'edit.php?post_type=jobs',
    'Active Jobs',
    'Active Jobs',
    'manage_options',
    'edit.php?post_type=jobs&jobstatus=67'
);

you could try and change the ampersand to its html entity equivalent

&amp;

so you would have

add_submenu_page(
    'edit.php?post_type=jobs',
    'Active Jobs',
    'Active Jobs',
    'manage_options',
    'edit.php?post_type=jobs&amp;jobstatus=67'
);

this worked for me... i also tested the output string for submenu and parent menu and checked if they match. this can be a little utility function for checking this stuff out

add_filter( 'parent_file', 'test_taxonomy_highlight' );
function test_taxonomy_highlight( $parent_file ){
   global $submenu_file;
   echo '<pre>', var_dump( $submenu_file, htmlentities( $submenu_file ) ), '</pre>';
   echo '<pre>', var_dump( $parent_file, htmlentities( $parent_file ) ), '</pre>';
   return $parent_file;
}
1

Thanks to all the other answers for leading me here.

The clue was the hook parent_file - however in the answers above, I see it being used to to access the global $submenu_file in order to set the active submenu.

After a bit more digging I found there is a hook submenu_file - which you can use instead to set the active submenu (which is better than overriding a global variable).

Usage is pretty much the same:

add_filter('submenu_file', 'wpse44270_submenu_file');

function wpse44270_submenu_file( $submenu_file, $parent_file ) {
    if (isset($_GET['jobstatus']) && $_GET['jobstatus'] == 67) {
        return 'edit.php?post_type=jobs&jobstatus=67';
    }
    return $submenu_file;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.