1

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.

2
  • 1
    it could be done via jquery probably... are all of these Service post-types actually in the menu?
    – GhostToast
    Commented Nov 4, 2013 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. Commented Nov 4, 2013 at 19:27

4 Answers 4

5

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;
}
9
  • 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. Commented Nov 4, 2013 at 19:27
  • I updated my answer with a way of doing it if your cpt is not created as a plugin.
    – Joey Yax
    Commented Nov 4, 2013 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. Commented Nov 4, 2013 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
    Commented Nov 5, 2013 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. Commented Nov 5, 2013 at 11:19
3

This code add class 'current-menu-item' to parent item menu of your child CPT or custom taxonomy or default single post, in case you do not have a nested menu structure in the admin panel - only if you have 'level 0' menu. For example - if you have Page Product, which display products grid and you go to the single product - WP will not see the parent menu item. The code below improve this:

function additional_active_item_classes( $classes = array(), $menu_item = false ) {
    // custom taxonomy
    if ( $menu_item->title == 'Custom Tax Name Page' && is_tax('custom_tax') ) {
        $classes[] = 'current-menu-item';
    }
    // custom post type single
    if ( $menu_item->title == 'Custom Post Type Page' && is_singular('products') ) {
        $classes[] = 'current-menu-item';
    }
    // blog post single
    if ( $menu_item->title == 'Blog Page' && is_singular('post') ) {
        $classes[] = 'current-menu-item';
    }
    return $classes;
}
add_filter( 'nav_menu_css_class', 'additional_active_item_classes', 10, 2 );
1
  • Hi Marek, while your code might be correct, could you elaborate and explain a little bit why this is the answer and how it works, so other people may learn from it? Commented Apr 5, 2019 at 10:40
2

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);
1

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?

7
  • 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? Commented Nov 5, 2013 at 11:24
  • Are you using a custom menu?
    – Joe
    Commented Nov 5, 2013 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' )); Commented Nov 5, 2013 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
    Commented Nov 5, 2013 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? Commented Nov 5, 2013 at 12:50

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.