For your particular situation, where you need to have a menu registered, but not shown unless you click on it from a link on another page you can add a conditional check to see if you’re on the editing page. If so, then change replace null
with book
per the add_submenu_page()
parameters.
add_action( 'admin_menu', 'add_the_menus' );
function add_the_menus() {
// Top level menu
add_menu_page( 'Books', 'Books', 'publish_posts', 'books', 'render_books_page', '', 17 );
// Adding this function to make the first submenu have a different name than the main menu
add_submenu_page( 'books', 'Books', 'All Books', 'publish_posts', 'books', 'render_books_page' );
// The Add Book menu page
add_submenu_page( 'books', 'Add New Book', 'Add Book', 'publish_posts', 'add-book', 'render_add_book_page' );
// Check the get parameter for page to see if its the page you want to display in the menu only when you're on it.
if ( $_GET['page'] === 'edit-book' ) {
// The Edit Book menu page (this page is hidden from the menu, and accessed via the All Books page only)
add_submenu_page( 'books', 'Edit Book', 'Edit Book', 'publish_posts', 'edit-book', 'render_edit_book_page' );
} else {
// The Edit Book menu page (this page is hidden from the menu, and accessed via the All Books page only)
add_submenu_page( null, 'Edit Book', 'Edit Book', 'publish_posts', 'edit-book', 'render_edit_book_page' );
}
}
An additional note. If it turns out that you need to also keep that menu item hidden even when selected you can enqueue a style to hide it only when you’re on that page.
add_action( 'admin_enqueue_scripts', function () {
if ( $_GET['page'] === 'edit-book' ) {
wp_enqueue_style( 'book-edit', get_stylesheet_directory_uri() . '/assets/css/book-edit.css' );
}
} );
Where the contents of book-edit.css would be something as simple as:
#toplevel_page_books li.current {
display: none;
}