0

I currently built a pretty simple tool to create a mega menu. I add a checkbox to my menu items in the Appearance > Menus section followed by a dropdown that includes template files within the theme.

Here's how my current function works (or doesn't work):

function mega_menu_start_el( $output, $item, $depth, $args, $id = 0 ) {

$is_mega = FALSE; $in_mega = FALSE; if( $depth > 0 ) { $parent_ID = get_post_meta( $item->ID, '_menu_item_menu_item_parent', TRUE ); if( $parent_ID ) { while( $parent_ID ) { //get the root parent $current_ID = $parent_ID; //on the late iteration, current_ID will hold the root parent $parent_ID = get_post_meta( $parent_ID, '_menu_item_menu_item_parent', TRUE ); } $in_mega = get_post_meta( $current_ID, 'menu-item-make-mega', TRUE ); } } else { $is_mega = get_post_meta( $item->ID, 'menu-item-make-mega', TRUE ); } if( $in_mega ) { return; } elseif( !$is_mega ) { return $output; } else { $template = get_post_meta( $item->ID, 'menu-item-mega-tpl', TRUE ); if( file_exists( $template ) ) { $mega_menu = '%s<div id="mega-menu-%s" class="mega-menu mega-menu-%s">%s</div>'; ob_start(); include( $template ); $mega_menu_output = ob_get_clean(); return sprintf( $mega_menu, $output, $item->ID, basename( str_replace( '.', '-', $template ) ), $mega_menu_output ); } } 

}

Now this kind of works because if the menu item isn't a mega menu it just returns the default generated output, if it's in a mega menu it clears the output, and if it is a mega menu then it load the template and adds it next to the link like a sub-menu.

The problem is, since I can't seem to find where the default sub-menu is generated, I still have the empty sub-menu markup (because clearing the output only clears the anchor tag and whatever is set in the "before" and "after" args):

<ul class="sub-menu"> <li id="menu-item-105" class="menu-item menu-item-type-post_type menu-item-object-product menu-item-105"></li> <li id="menu-item-106" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-106"></li> <li id="menu-item-107" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-107"></li> </ul> 

So basically I'd like to hook into a level higher than this and check if I'm in a mega menu and if it is the case, then just nuke it.

I've been wrestling with this for a while so any tips would be super appreciated.

Thank you

Edit: Okay so I think doing this with the filters is impossible because there's no filter for start_lvl (only start_el). This means I have to build a custom walker to achieve this, something I wanted to avoid to circumvent possible conflicts with themes that might already use a custom walker for their menu.

I was able to achieve what I wanted with a walker that extends the default Nav_Menu_Walker class. For anyone that is curious, I modified the function above so that it adds to the $output variable instead of returning anything.

I also added a private variable to hold whether we are currently in a mega menu since the walk method will traverse through the tree from the root parent and then all the way down to its children. This means I can set $this->_in_mega at the same time as $is_mega. Then, when I'm in start_lvl() and end_lvl() I call parent::start_lvl() or parent::end_lvl() if we're not currently in the mega menu.

I'm going to leave my question open as I was hoping for a different solution (and someone could provide one) but for now, this works well enough for me.

1 Answer 1

0

best and easy way to hide submenu is to use css

.sub-menu { display: none !important; } 

Or you can use 'depth'=>1

 `wp_nav_menu( array( 'menu_id'=>'nav', 'theme_location'=>'header-menu' , 'depth' => 1) ); 

or create a function to set the 'depth'=>1 for a perticular menu. place this code in your theme function.php

 add_filter( 'wp_nav_menu_args', 'remove_my_header_dropdown', 1, 1 ); function remove_my_header_dropdown( $args ) { //lookup theme_location ie: top-menu if ( isset( $args['theme_location'] ) && 'top-menu' == $args['theme_location'] ) { $args['depth'] = 1; //levels of the hierarchy are to be included } return $args; } 

` Hope that works for you

2
  • I don't know if I would agree that it's the best way but it's certainly easy :-P I was hoping to find a way that would avoid a CSS or JS fix as I feel the start_el hooks seem to be a correct way to go about it... I feel like I'm so close. Thank you for your input. Commented Feb 21, 2018 at 18:19
  • 1
    I have update my answer and added one more option for you. hope that work. Commented Feb 21, 2018 at 20:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.