How to set limit only on top levels of wp_nav_menu?

How can I set a limit to the top level menu items in wp_nav_menu?

Example:

Read More

I have this menu in my admin dashboard:

Example menu

I would like to count ONLY the top level items and display a limited number of them, let’s say 5.

So no matter if you’re in the admin dashboard and you have 100’s of top levels, it should only display 5.

The sub-pages should be displayed as well, normally, without any limit.

I searched for an answer here and on the web and I saw this answer but big problem is that this solution counts top and sub-pages altogether and I need to count only top pages.

I would like to see some solution with a custom walker class if possible or PHP in general and not with CSS and jQuery tricks and hacks.

Related posts

Leave a Reply

3 comments

  1. According to the codex, you just need to use depthparameter to display only top-level pages :

    <?php wp_nav_menu( array( 'location' => 'your_location', 'depth' => 1 ) ); ?>
    

    For more reference see this.

    You could also fix both of your problem by using [wp_get_nav_menu_items][2] and then using a custom loop to parse only first and top-level pages.

    EDIT***
    I did spent some time starting something to help, unfortunately I cannot finish it right now, and maybe could make it more elegant, but that could be a start :

    <?php 
        $menu_name = 'principal';
            if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
            $menu_test = wp_get_nav_menu_object( $locations[ $menu_name ] );
                        // WE GET THE ITEMS IN menu_order
            $menu_test_items = wp_get_nav_menu_items( $menu_test->term_id );
            $top_items = array();
                        // LOOP THEM AND CREATE NESTED ARRAY LIKE THE MENU 
            foreach( $menu_test_items as $menu_test_item ) {
                if ( $menu_test_item->menu_item_parent == 0 ) {
                    $top_items[$menu_test_item->ID][$menu_test_item->ID] = $menu_test_item;     
                } else {
                    $top_items[$menu_test_item->menu_item_parent][$menu_test_item->ID] = $menu_test_item;
                }
    
            }
                        // THEN WE COULD JUST LOOP IT x TIMES AND BREAK
            foreach ( $top_items as $top_item ) {  
                // Npw you need to loop x times
                // and display $top_item with another foreach
            }
        }
    ?>
    
  2. you can try something like:

    function my_max_5_menu_items( $menu_items) {
    
        return array_slice( $menu_items, 0, 5 );
    
    }
    add_filter( "wp_nav_menu_items", "my_max_5_menu_items" );
    

    Did not had the chance tot test this.

  3. For reference, Sormano was on the right path, but the filter passes a string. The correct version would be:

    function my_max_5_menu_items( $menu_items) {
        $menu_items = explode('</li>', $menu_items);
    
        $menu_items = array_slice( $menu_items, 0, 5 );
    
        return implode('</li>', $menu_items);
    }
    add_filter( "wp_nav_menu_items", "my_max_5_menu_items" );
    

    Obviously, this only works when you also use depth=1. But it is a simpler solution to creating a customer walker if all you need is a simple solution.