Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Im having a problem with my menu and custom post type.

I have a custom post type of "services". I have created new page for it called Services. On that page Im displaying a list of all the post from that custom post type. The current-menu-item class is working as itended.

But the problem is when I click on one of the services and go to mysite.com/services/service-1, the current-menu-item from services page in menu dissapears. I need to show that this current post is a child of Services page.

All of the menu items have the same HTML:

<li id="menu-item-23" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-23"><a href="http://localhost/wordpress/sluzby/">Služby</a></li>

There is no CSS class that I could use to style this link as parent. Something like current-menu-parent or something. How could I fix this? Thanks.

share|improve this question
1  
it could be done via jquery probably... are all of these Service post-types actually in the menu? –  GhostToast Nov 4 '13 at 18:00
    
@GhostToast actually its only one single item in the menu called Services. When you click it opens page Services which has a loop and displays all the services posts. –  Richard Mišenčík Nov 4 '13 at 19:27
add comment

3 Answers 3

up vote 3 down vote accepted

I usually include the following parent variable, filter and method in my plugins to account for this case. I've never been sure if this is the "right" way of going about it, but feels better than applying it with javascript.

class Plugin_Name {
    private $parent = 'services'; // ideally this is a setting in your plugin, not a hard-coded variable in case the page slug changes

    function __construct() {
        // Add classes to 'parent'
        add_filter( 'nav_menu_css_class', array( &$this, 'nav_parent_class' ), 10, 2 );
    }

    function nav_parent_class( $classes, $item ) {

        if ( $this->nicename == get_post_type() && ! is_admin() ) {
            global $wpdb;

            // remove any active classes from nav (blog is usually gets the currept_page_parent class on cpt single pages/posts)
            $classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor'  || $class == 'current-menu-item' ? false : true ));

            // get page info
            // - we really just want the post_name so it cane be compared to the post type slug
            $page = get_page_by_title( $item->title, OBJECT, 'page' );

            // check if slug matches post_name
            if( $page->post_name == $this->parent ) {
                $classes[] = 'current_page_parent';
            }

        }

        return $classes;
    }
}

Per your request, non-plugin route. I didn't test this for any errors, just adapted from the class above but it should at least get you in the right direction:

add_filter( 'nav_menu_css_class', 'nav_parent_class', 10, 2 );

function nav_parent_class( $classes, $item ) {
    $cpt_name = 'service';
    $parent_slug = 'services';

    if ( $cpt_name == get_post_type() && ! is_admin() ) {
        global $wpdb;

        // remove any active classes from nav (blog is usually gets the currept_page_parent class on cpt single pages/posts)
        $classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor'  || $class == 'current-menu-item' ? false : true ));

        // get page info
        // - we really just want the post_name so it cane be compared to the post type slug
        $page = get_page_by_title( $item->title, OBJECT, 'page' );

        // check if slug matches post_name
        if( $page->post_name == $parent_slug ) {
            $classes[] = 'current_page_parent';
        }

    }

    return $classes;
}
share|improve this answer
    
How would I do that non plugin way, I would like to insert it in my functions.php but I suppose it has to be modified. –  Richard Mišenčík Nov 4 '13 at 19:27
    
I updated my answer with a way of doing it if your cpt is not created as a plugin. –  Joey Yax Nov 4 '13 at 20:44
    
That doesnt seem to work for me. I changed the variables but still. If I understood correctly, is the code checking for post name and comparing to the slug? I dont think that would work since my CPT is called services. But im using rewrite to "sluzby", which in my language translates to services. But my services post dont contain that slug, I mean the service can be called Webdesign for example, no Service Webdesign. So the page that is used to display my services posts is localhost/wordpress/sluzby. Then the single posts are at localhost/wordpress/sluzby/name-of-post. –  Richard Mišenčík Nov 4 '13 at 20:54
    
It's checking two things: 1) If the post being viewed is from your custom post type ($cpt_name) and 2) looks for the nav item slug equal to $parent_slug. If both of those match it adds a current_page_parent class to that nav item. –  Joey Yax Nov 5 '13 at 0:01
    
Im not sure if Im doing something wrong but it still doesnt work. Here is my current code: function nav_parent_class( $classes, $item ) { $cpt_name = 'services'; $parent_slug = 'sluzby'; if ... return $classes; } So my custom post type name is "services" and my URL for services page is localhost/wordpress/sluzby. Then each individual service is here localhost/wordpress/sluzby/name-of-service. I checked the source code but the class is not being added and all of the other classes dissapeared. I also changed my CSS to include the styles for this class too. –  Richard Mišenčík Nov 5 '13 at 11:19
show 4 more comments

Final code:

function nav_parent_class($classes, $item) {
    $cpt_name = 'services';
    $parent_slug = 'sluzby';

    if ($cpt_name == get_post_type() && !is_admin()) {
        global $wpdb;

        // get page info (we really just want the post_name so it can be compared to the post type slug)
        $page = get_page_by_title($item->title, OBJECT, 'page');

        // check if slug matches post_name
        if( $page->post_name == $parent_slug ) {
            $classes[] = 'current_page_parent';
        }

    }

    return $classes;
}

add_filter('nav_menu_css_class', 'nav_parent_class', 10, 2);
share|improve this answer
add comment

Normally there is a class of .current-menu-ancestor added to parent items in the navigation.

If its not there have a look at this post: How to include the 'current-menu-ancestor' class on a custom post type menu in Wordpress?

share|improve this answer
    
not working for me. Could it be because Im using rewrite and therefore having different name for custom post type and for the page itself? –  Richard Mišenčík Nov 5 '13 at 11:24
    
Are you using a custom menu? –  Joe Nov 5 '13 at 12:06
    
This is the code I use: wp_nav_menu(array( 'container' => false, 'container_class' => '', 'menu' => '', 'theme_location' => 'main-nav', 'items_wrap' => '<ul id="menu">%3$s</ul>', 'fallback_cb' => 'rm_main_nav_fallback' )); –  Richard Mišenčík Nov 5 '13 at 12:29
    
And you have the menu defined in the admin area under Appearance->Menus If you do, and the menu is still not providing the class. This is not a problem I have come across. –  Joe Nov 5 '13 at 12:40
    
Yes, I have created Menu with all the links in it. I think it could be a problem with rewrite since my CPT name is services but my URL for that page is wordpress/sluzby. Im really clueless. Is there anything else I could try? –  Richard Mišenčík Nov 5 '13 at 12:50
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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