A new Advanced Custom Field type lets you select any WordPress menu.

A new Advanced Custom Field type lets you select any WordPress menu.

I faced a recent challenge where a site needed to support different main menus on different parent pages. I'm a big fan of Advanced Custom Fields and immediately knew that it would be the perfect tool for the job.

There were 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.

I grappled with the ACF Relationship field first, but it wouldn’t allow me to nest pages natively. There was a thought that “Maybe the user could select the parent pages and the menu will build itself,” but the project requirements dictated otherwise.

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

Briefly — I performed research but quickly pivoted to, “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 fields; after all, they’ve done such an amazing job doing just that for years now.

I dived right into their boilerplate repo and had to figure out where I would be writing my code.

Here’s what I found.

function render_field( $field ) {

}

Turns out — this is where I needed to write the code. The idea was to expose a new field type where an array of menu ids would power the data.

Here what I did to get the menu ids:

$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 slick-looking dropdown with a search field inside 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 are a few things that are required if you want to use the select2 or “fancy select dropdown.”

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

Here’s what it all looks like put together.

function render_field( $field ) {
        $field['type']  = 'select';
        $field['ui']    = 1;
        $field['label']    = '';

        $menus = wp_get_nav_menus();

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

        acf_render_field_wrap($field);
    }

With this in place — we now have the ability to create a new menu field for our pages. When the user makes a selection — the ACF function get_field() will return the menu ID. You can use this ID to display the menu using the WP functionwp_nav_menu().

Here's what it looks like in action.

Demonstrating new ACF menu field type

Pretty sweet — yea? Let's see what it looks like when editing a page.

Demonstrating the new ACF menu field in action when editing a page

If you find yourself needing this type of functionality — hopefully, this saves you some time.

You can download the plugin here.

Cheers! 🎉

Did you find this article valuable?

Support Code for humans by becoming a sponsor. Any amount is appreciated!