WordPress ACF Menu Picker
Posted Thursday, October 26, 2023
I needed the ability for a CMS user to choose a standard WordPress menu via an ACF field. Here’s the solution.
- Make your field. In my example, it’s called
navigation_menu
. - Add the below filter hook to your
functions.php
/**
* Create an ACF field for selecting a menu
*/
function namespace_populate_menus_field( array $field ): array {
// Reset choices
$field['choices'] = [];
// Get all registered menus and add them to the field with slug as value and name as label
foreach ( wp_get_nav_menus() as $menu ) {
$field['choices'][ $menu->slug ] = $menu->name;
}
// Sort choices alphabetically
ksort( $field['choices'] );
return $field;
}
add_filter( 'acf/load_field/name=navigation_menu', 'namespace_populate_menus_field', 10, 1 );
And voila. Your select should automatically be populated with all the menus you’ve already got in WordPress.
If you’d prefer to only offer the menus that aren’t already assigned to a menu “location,” here’s how to modify the code to find all the locations and all the relationships between menus and locations, and filter out the assigned ones.
function namespace_populate_menus_field( array $field ): array {
// Reset choices
$field['choices'] = [];
// Retrieves all registered navigation menu locations and the menus assigned to them
$all_locations = get_nav_menu_locations();
// Returns all navigation menu objects
$all_menus = wp_get_nav_menus();
// Get registered menu IDs
$registered_ids = [];
// Loop through all registered navigation menu locations in the theme
foreach ( array_keys( get_registered_nav_menus() ) as $menu ) {
// If the menu has been assigned to a location add the menu ID to the array of registered menu IDs
if ( isset( $all_locations[ $menu ] ) ) {
array_push( $registered_ids, $all_locations[ $menu ] );
}
}
// Loop through all navigation menus
foreach ( $all_menus as $menu ) {
$menu_id = $menu->term_id;
// If the menu is not registered then add as a choice
if ( ! in_array( $menu_id, $registered_ids ) ) {
$field['choices'][ $menu->slug ] = $menu->name;
}
}
// Sort choices alphabetically
ksort( $field['choices'] );
return $field;
}
add_filter( 'acf/load_field/name=navigation_menu', 'namespace_populate_menus_field', 10, 1 );