Code for humans.

Creating a new ACF field type that allows you to select any WordPress menu.

Chris Miller
Chris Miller

Creating a new ACF field type that allows you to select any WordPress menu.

Just when you thought you had seen it all. There was a recent challenge where a site needed to support different menus on different page.

To be more specific, there are 40 parent pages that each required their own navigation. Under each of the 40 parent pages would be several children pages and probably children of children and so on.

TLDR; You can checkout the plugin at GitHub - millertchris/acf-menu-field: A custom field for ACF that allows you to select any WordPress menu.

I grappled with the ACF Relationship field at first but it wouldn’t allow nesting pages natively. There was also a thought that “Maybe the user could just selected parent pages and the menu will build itself” but the project requirements dedicated otherwise.

Ultimately the user would need to control both nesting and order.

Briefly, I performed research but quickly thought “Hey, I bet it wouldn’t be too difficult to make my own ACF field.”

Then I found this. ACF | Creating a new field type

Of course Elliot Condon and his team would make it dead simple for developers to create their own fields, after all, they’ve done such an amazing job doing just that for years now.

I dived right into the their boilerplate repo and quickly got to work. The first thing I had to do was figure out where I would be writing my code in order for it to display in the editor.

Here’s what I found.

/*
*  render_field()
*
*  Create the HTML interface for your field
*
*  @param   $field (array) the $field being rendered
*
*  @type    action
*  @since   3.6
*  @date    23/01/13
*
*  @param   $field (array) the $field being edited
*  @return  n/a
*/

function render_field( $field ) {
    
}

This was exactly what I needed! Now, the idea was to expose a new field type where the data would be powered by an array of menu id’s.

Here what I did to get the menu id’s:

$menus = wp_get_nav_menus();

foreach ($menus as $key => $value) {
    $field['choices'][$value->term_id] = $value->name;
}

That was pretty easy! However, this next part, not so much.

I wanted to use the select2 dropdown field that ACF uses, you know, that really slick looking dropdown that has a search field inside of it?

The reason was not purely based on bias, remember, there will be 40 pages that need 40 different menus and that’s a lot to scroll through!

After doing some Google searching I was able to find this little gem.

$field['type']  = 'select';
$field['ui']    = 1;
$field['label'] = '';

acf_render_field_wrap($field);

Turns out, there’s a few things that are required when wanting to use the select2 or “fancy select dropdown”.

Setting both the type to “select” and the ui to “1” are required. Then acf_render_field_wrap($field) brings the magic sauce.

Here’s what it all looks like put together.