As far as I can know about menus in WordPress – handlers use menu arguments. You can try to use this.
Using the argument filter, we can pass the ID of the item:
add_filter(
'nav_menu_item_args',
function( $args, $item, $depth ) {
$args->item_id = $item->ID;
return $args;
},
10,
3
);
Then use custom argument anywhere.
add_filter(
'walker_nav_menu_start_el',
function($item_output, $item) {
if ( get_field( 'dropdown', $item) == 'yes' ) {
return '<button aria-expanded="false" aria-controls="submenu-'. $item->ID . '" class="header__button">' . $item->title . '</button>';
}
return $item_output;
},
10,
2
);
class My_Nav_Menu_Walker extends Walker_Nav_Menu {
/**
* Starts the list before the elements are added.
*
* @see Walker::start_lvl()
*
* @param string $output Used to append additional content (passed by reference).
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = null ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t="";
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
// Default class.
$classes = array( 'sub-menu' );
// ! Get parent item ID:
$id = isset( $args->item_id ) ? ' id="submenu-' . absint( $args->item_id ) . '"' : '';
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @since 4.8.0
*
* @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$class_names = implode( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
// ! Insert ID:
$output .= "{$n}{$indent}<ul{$class_names}{$id}>{$n}";
}
}
It remains to include the file with an custom walker
and point it to the menu:
wp_nav_menu(
array(
'container' => false,
'theme_location' => 'primary',
'items_wrap' => '<ul class="header__nav-items header__nav-items--primary">%3$s</ul>',
'walker' => new My_Nav_Menu_Walker()
)
);
I have not tested the code. In some cases there can be a conflict and you can either use clone
for the menu argument, or use another way to limit the scope of an custom argument.