Dynamic Dropdown Fields in ACF

Advanced Custom Fields is a powerful tool for building metaboxes, theme settings, custom blocks, and more.

The acf/load_field filter lets you customize a field before it loads. I often use it for dynamically populating dropdown lists.

These code snippets can go in your theme’s functions.php file or a Core Functionality plugin.

Selecting a form

When a site contains multiple forms that might need to change over time, I like to create a site options page for managing which forms appear where.

The acf/load_field filter runs before each field loads. I’ll then check to see if the field name matches the ones I have for the Subscribe and User Registration forms, and if so I’ll populate $field['choices'] with all the forms we have on the site.

I’m using WPForms so will use wpforms()->forms->get() to list all forms, but you could do the same thing with Gravity Forms (example) or any other form plugin.

/**
 * Dynamically select form in ACF
 * @see https://www.billerickson.net/dynamic-dropdown-fields-in-acf/
 * @author Bill Erickson
 *
 * @param array $field, the field settings array 
 * @return array $field
 */
function be_acf_select_form( $field ) {

	// These are the field names we're updating
	$form_fields = array( 
		'ea_subscribe_form', 
		'ea_registration_form,' 
	);
	
	if( ! in_array( $field['name'], $form_fields ) )
		return $field;

	// Get form list from WPForms
	if( ! function_exists( 'wpforms' ) )
		return $field;
	$forms = wpforms()->form->get();

	// Build list of choices
	$field['choices'] = array( 0 => '(None)' );
	foreach( $forms as $form ) {
		$field['choices'][ $form->ID ] = $form->post_title;
	}
	return $field;
}
add_filter( 'acf/load_field', 'be_acf_select_form' );

When you need to display the form, you pull the form ID from the Site Options page.

Using ACF function: get_field( 'ea_subscribe_form', 'options' );
Using WP function: get_option( 'options_ea_subscribe_form' );

Display WPForm: wpforms_display( $form_id )
Display Gravity Form: gravity_form( $form_id )

I use this approach to define theme locations for forms, which adds a class of .location-subscribe to the subscribe form. I can then style the form using this class rather than the form ID, which ensures the styling continues to work if the form assigned to the “Subscribe” location changes.

Selecting an icon

On my homepage I have an Industries block with an icon for each industry.

WordPress Developer for…

Law Firms

Your website needs to reflect the quality and professionalism of your practice.

Publishers

Your website needs a captivating design that keeps readers engaged and load fast at scale.

Non-Profits

You need a website that 
keeps stakeholders 
engaged, communicates 
your story, and supports 
your fundraising efforts.

Corporations

Your website needs flexible landing pages that are easy to build, on-brand, and can track success.

The icons are stored as SVGs in my theme’s /assets/icons/category directory. In the ACF block metabox, the select dropdown dynamically lists all icons in that directory.

Since I want this to only apply to a single field (name=”icon”), we can use a more specific filter: acf/load_field/name=icon.

/**
 * Dynamically select icon in ACF
 * @see https://www.billerickson.net/dynamic-dropdown-fields-in-acf/
 * @author Bill Erickson
 *
 * @param array $field, the field settings array 
 * @return array $field
 */
function be_acf_select_icon( $field ) {

	$field['choices'] = array( 0 => '(None)' );
	$icons = ea_get_theme_icons( 'category' );
	foreach( $icons as $icon ) {
		$field['choices'][ $icon ] = $icon;
	}

	return $field;
}
add_filter( 'acf/load_field/name=icon', 'be_acf_select_icon' );

/**
 * Get Theme Icons
 * Refresh cache by bumping CHILD_THEME_VERSION
 */
function ea_get_theme_icons( $directory = 'utility' ) {
	$icons = get_option( 'ea_theme_icons_' . $directory );
	$version = get_option( 'ea_theme_icons_' . $directory . '_version' );
	if( empty( $icons ) || ( defined( 'CHILD_THEME_VERSION' ) && version_compare( CHILD_THEME_VERSION, $version ) ) ) {
		$icons = scandir( get_stylesheet_directory() . '/assets/icons/' . $directory );
		$icons = array_diff( $icons, array( '..', '.' ) );
		$icons = array_values( $icons );
		if( empty( $icons ) )
			return $icons;
		// remove the .svg
		foreach( $icons as $i => $icon ) {
			$icons[ $i ] = substr( $icon, 0, -4 );
		}
		update_option( 'ea_theme_icons_' . $directory, $icons );
		if( defined( 'CHILD_THEME_VERSION' ) )
			update_option( 'ea_theme_icons_' . $directory . '_version', CHILD_THEME_VERSION );
	}
	return $icons;
}

To display the icon, we use the ea_icon() function in our theme (see here).

$icon = get_field( 'icon' );
if( !empty( $icon ) )
	echo ea_icon( array( 'icon' => $icon, 'group' => 'category' ) );

Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments

Leave A Reply