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.


  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.