7

I have a custom plugin 'Charts' that has it's own menu. In that menu are links to the 3 pages for the plugin - 'Charts', 'Add Chart' and 'Edit Chart'. However, I don't want to display the link to 'Edit Chart'.

Here is how I add the page in question -

$this->pagehook = add_submenu_page('charts', __('Edit Chart'), __('Edit Chart'), 'edit_charts', 'edit-chart', array(&$this, 'on_show_page'));

I've scoured the internet, and cannot find a way to do this (that works). It's possible to remove whole top level menus (not what I need), and you can remove individual entries from the $submenu global (but doing that also removes the registered capability), so no one can access the page -

global $submenu;
if(!empty($submenu['charts'])) : foreach($submenu['charts'] as $key => $page) :
        if($page[0] === 'Edit Chart') :

            /** Removes all permissions to access the page */
            //unset($submenu['charts'][$key]);              
            /** Removes the title, but the menu entry still exists, so it looks odd */
            $submenu['charts'][$key][0] = '';

        endif;
    endforeach;
endif;

I've looked in to hiding it via CSS, but can't see a way to do that through the HTML that Wordpress generates -

<li><a href="admin.php?page=edit-chart" tabindex="1">Edit Chart</a></li>

I've also considered jQuery, but that has similar limitations to the CSS route, plus I refust to believe that I am the only one that has ever wished to do this - there must be a way, I just can't find it!

Any hints and tips appriciated.

Thanks.

  • Where are you hooking this function? What filter/action? – s_ha_dum Nov 22 '12 at 14:45
8

Use a submenu page as parent slug. The admin menu has just two levels, so the imaginary third level will be hidden.

Sample code, tested:

add_action( 'admin_menu', 'wpse_73622_register_hidden_page' );

function wpse_73622_register_hidden_page()
{
    add_submenu_page(
        'options-writing.php',
        'Hidden!',
        'Hidden!',
        'exists',
        'wpse_73622',
        'wpse_73622_render_hidden_page'
    );
    # /wp-admin/admin.php?page=wpse_73622
}

function wpse_73622_render_hidden_page()
{
    echo '<p>hello world</p>';
}
  • This does work, although what doesn't work is the active state on the parent menu item get's lost, so the submenu closes, and no menu parent item is selected in the left sidebar. – Lee Aug 1 '16 at 9:50
23

From the docs on add_submenu_page(), you see that you can hide your submenu link from a top level menu item to which it belongs be setting the slug (1st argument) to null:

add_action( 'admin_menu', 'register_my_custom_submenu_page' );

function register_my_custom_submenu_page() {
    add_submenu_page( 
        null,
        'My Custom Submenu Page',
        'My Custom Submenu Page',
        'manage_options',
        'my-custom-submenu-page',
        'my_custom_submenu_page_callback',
    );
}

To highlight the desired menu item (e.g. 'all charts' when accessing the hidden 'edit chart' page), you can do the following:

add_filter( 'submenu_file', function($submenu_file){
    $screen = get_current_screen();
    if($screen->id === 'id-of-page-to-hide'){
        $submenu_file = 'id-of-page-to-higlight';
    }
    return $submenu_file;
});
  • Cool, but highlighting don't work correctly. If i set submenu_file they displayed as current. But top level menu not opened. But if i set parent_file, wp run function get_admin_page_parent() after filters and change it back. For what wp developers add parent_file filter if anyway function change it back. Could you help? – DARK_DIESEL Aug 28 '18 at 13:11
  • Also if parent_slug set as null, page_title not used in title. – DARK_DIESEL Aug 28 '18 at 13:12
  • You can use 'options.php' instead off null. – RavanH Mar 19 at 23:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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