How to Create ACF Nested Select / Optgroup

A nested select using is still a missing basic feature from ACF. In today's tip, we are going to learn how to enable it.

Update 16 Oct 2020: Code snippet has been updated to support version 5.9.x

A nested select using <optgroup> is still a missing basic feature from ACF.

In today’s tip, we are going to learn how to enable nested options just like shown below:

ACF Select field with nested options

The Choices Format

ACF Select configuration

The Choices setting is just a plain textarea (shown above), so we need to determine a format to know which one is the group label.

For this example, the line that begins with # will be turned into group label.

Here’s the setting of our Choices:

us : United States
ca : Canada
mx : Mexico
uk : United Kingdom
de : German
fr : France

The Hook

What we are trying to achieve is to create a nested Array using the group label as it’s parent. Then pass it to the choices argument.

// Don't forget to change the 'name'
add_filter('acf/prepare_field/name=country', 'acf_allow_optgroup');

function acf_allow_optgroup( $field ) {
  // Abort if it's native option
  if( $field['ID'] === 0 ) { return $field; }

  $raw_choices = $field['choices'];
  $choices = [];

  $current_group = '';
  foreach( $raw_choices as $value => $label ) {

    // if first letter is hashtag, turn it into group label
    if( preg_match( '/^#(.+)/', $label, $matches ) ) {
      $current_group = str_replace( '#', '', $label );
      $choices[ $current_group ] = [];
    // If group label already defined before this line
    elseif( !empty( $current_group ) ) {
      $choices[ $current_group ][ $value ] = $label;
    else {
      $choices[ $value ] = $label;

  $field['choices'] = $choices;
  return $field;

That’s all! Don’t forget to change the filter name to fit your field.


This is one of those little things that make it easier for my client to edit their own site.

I hope the ACF developer will add a native way to do this. I actually notified him back in 2017 via this Github thread but I don’t think he will add it.

As always, ask any question about ACF Nested Select in the comment below 🙂

Default image
Henner Setyono
A web developer who mainly build custom theme for WordPress since 2013. Young enough to never had to deal with using Table as layout.
Leave a Reply


  1. Thanks and awesome job! It worked perfectly 🙂

    I did change it to work on all select fields w/:

    add_filter('acf/prepare_field/type=select', 'acf_allow_optgroup');
    • Thanks, glad you find it useful.

      The reason why I use a specific field name for the filter is to have better performance. But I don't think it's even slightly noticeable.