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:
The Choices Format
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:
#America
us : United States
ca : Canada
mx : Mexico
#Europe
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.
Conclusion
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 🙂
Thanks and awesome job! It worked perfectly 🙂
I did change it to work on all select fields w/:
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.
Thanks @Henner for this suggestion.
How can we do this for Taxonomy ACF select field, where options are coming from taxonomy which has nested parent-child heirarcy?
Hi Sandy, I just checked my Taxonomy ACF Select. It automatically list them in parent-child order. So you don't need to write any custom code.
Thanks for prompt response 🙂
Yes, it shows in parent-child by default by adding the prefix of a hyphen (-) and increments based on the child e.g. below.
How can we make optgroup for all the parents, where all these choices are coming from taxonomy?
Hi, I guess we can use the
prepare_field
filter as seen in this article to do this. Usevar_dump($field)
to see what you can modify.If it works the same way as a SELECT field, then it will be an optgroup if you return a nested array.
Unless you want to make the parent category not selectable by maknig it optgroup, just stick with the native one.