WordPress.org

Support

Support » Plugins and Hacks » Hacks » [Resolved] Removing nav_menu from custom page templates

[Resolved] Removing nav_menu from custom page templates

  • Hello.

    I’ve created a new custom page template for a child theme (parent theme is Hybrid).

    This custom page template will be used for landing page and will need a less cluttered layout.

    In my functions.php, I’ve already removed all widgets (I’ll see later if and which widget to put back), but I also need to remove all menus from this page: no navigations, no widget (yet), but just some layout and specific contents.

    For the widgets, I’ve simply set the $sidebars_widgets to an empty array, but I don’t know what to do it with nav_menu objects/locations.

    My last attempt is to hook a function to the ‘init’ action:

    function landing_page_template_nav_menus() {
    	if (is_page_template('page-landingpage.php')) {
    		$locations = get_nav_menu_locations();
    		foreach ($locations as $location)
    		{
    			unregister_nav_menu($location);
    		}
    	}
    	return $sidebars_widgets;
    }

    Of course, this doesn’t work, most likely because the ‘init’ action doesn’t know yet the current page template.
    I could try with other hooks (actually I did with some of them, without results), but I’d like to use the right one.

    Of course I could also play with CSS, but I prefer to have unused/unwanted html totally removed from the page source.

    To clarify:
    I want to write the code as if I’m unaware of all nav_menu locations (to make the code more reusable in other themes). That’s why I’m trying to use a loop.

    Bottom line, I need to find when to call this function, i.e. the right hook.

Viewing 12 replies - 1 through 12 (of 12 total)
  • You could try template_redirect that should be early enough to make the changes you need, but late enough for conditional tags like is_page_template() to return correctly.

    Thank you Mark.

    The fact is that I’m not even sure my if code (see the code above, in my first post) is correct.

    However, I’ve just tried, but the menus still appears: If my code is right, then the template_redirect hook doesn’t help.

    You need to use the location, which in the array is the key not the value, update your loop to..

    foreach ($locations as $location => $n ) {
        unregister_nav_menu($location);
    }

    And see if that helps..

    Thank you again Mark.

    Unfortunately this is still not working.

    Just to verify that my function is called, I’ve added echo '**********'; right after $locations = get_nav_menu_locations(); and indeed, the function is called only once and the echo prints the start right at the beginning of the html (before the `<!DOCTYPE html>’).

    So, the code can see the right page template, I do unregister all nav_menu (with the code you’ve provided), but still nothing happens.

    I’ve also tried to move the echo '**********'; inside the foreach() and I get the stars printed three times, so, is indeed doing something.

    I suppose something else is putting them back.

    Is this function attached to the action i suggested?

    If so, it seems strange you have a return statement at the end referencing sidebar widgets.

    Would you mind clarifying what your function does(aside from the discussed aspects), and where it hooks.

    Yes, sorry: it has a return statement because in all my attempts, I’ve also tried using this function as a hook for a filter.
    The return as been removed in the current version of the code.
    And yes, right now is hooked to the template_redirect.

    To recap, I’m using Hybrid Theme. This is the current code (only the interested portions):

    [Code moderated as per the Forum Rules. Please use the pastebin]

    As you can see, I use the if ( !is_admin() ) function to check when to hook to some filters. However, I’ve tried also putting add_action('template_redirect', 'landing_page_template_nav_menus'); outside the if ( !is_admin() ), with no changes in the resulting html.

    Ok a little bit of misunderstanding on our part, all unregister_nav_menu does is unregister the location, which is easily evidenced by viewing the menu administration area, it does not remove menus already registered to that location though..

    I don’t have any ideas how to work around that just yet, but thought you might be interested to know the reasoning the code doesn’t act as expected.

    Did a little backtracing and looked at the functions that are called when menus are output, ultimately the problem is a result of the data stored elsewhere, but after a little fiddling around i worked out a way to filter that data to make sure the menu disappears.

    $locations = get_nav_menu_locations();
    
    add_action( 'template_redirect', 'test_menu_removal' );
    add_filter( 'theme_mod_nav_menu_locations', 'remove_from_theme_mods' );
    
    function test_menu_removal() {
    
    	if( is_page_template( 'page-landingpage.php' ) ) {
    		global $locations;
    
    		foreach( $locations as $location => $n ) {
    			unregister_nav_menu($location);
    		}
    		return;
    	}
    	remove_filter( 'theme_mod_nav_menu_locations', 'remove_from_theme_mods' );
    }
    
    function remove_from_theme_mods( $r ) {
    
    	global $locations;
    
    	foreach( $locations as $location => $n ) {
    		if( isset( $r[$location] ) )
    			unset( $r[$location] );
    	}
    	return $r;
    }

    Just remember, wp_nav_menu uses a fallback function when it can’t find a menu to display, and if memory serves that’s wp_page_menu, so whilst the above will essentially remove the menu, it does result in another menu being generated(the fallback – wp_page_menu).

    Hope that helps in any case… 🙂

    For reference, here’s the 3 files that contain the various functions i’ve been digging through(to save you needing to backtrace yourself), incase you want to get stuck in and see if you can find alternative / better ways to tackle what you need.

    http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/nav-menu.php
    http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/nav-menu-template.php
    http://core.trac.wordpress.org/browser/tags/3.2.1/wp-includes/theme.php

    Wow!

    This actually solved the problem. Now I’ll go through the code and reference links, to better understand what is doing it, but yes, it definitely works!

    Thank you very much Mark!

    P.S.: about the misunderstanding, I’m not too surprised: sometimes I forget that I’m not a native speaker and that I must be more clear when I write my issues 😉

    Happy to have helped… 🙂

    Best of luck with your site and coding.

    Following up on this, I have a similar problem…

    I’m developing a Hybrid prototype child theme strip out the ‘secondary’ menu location I don’t want on the interior pages.

    I can’t seem to get this to work for the functions.php file…

    How to remove a nav menu location in WordPress 3.0.0

    I know this is native to the base code as of 3.1 but I’n not sure what I’m doing wrong.

    I would rather avoid just hiding the menu with css or pulling out sidebars in the code but call it conditionally for the homepage and strip it out for the other templates to better future proof my child theme and leave the sidebar in for other purposes.

    Nevermind, after some sleep and caffeine I realized Prototype was circumventing normal tactics to register/call the menus so I edited menu-secondary.php in my child theme to be conditional for only my homepage and that worked…

    if ( has_nav_menu( 'secondary' ) && (is_front_page()) ) : ?>

Viewing 12 replies - 1 through 12 (of 12 total)
  • The topic ‘[Resolved] Removing nav_menu from custom page templates’ is closed to new replies.