Skip to content

Latest commit

 

History

History
239 lines (200 loc) · 7.05 KB

File metadata and controls

239 lines (200 loc) · 7.05 KB

Multi Select Field Type

The Multi Select field type allows users to select multiple options from a searchable dropdown. It provides a modern interface with add/remove functionality, making it ideal for categorization, tagging, or any scenario requiring multiple selections from a predefined set.

Field Type: multi_select

array(
	'type'    => 'multi_select',
	'id'      => 'example_multi_select',
	'label'   => 'Tags',
	'options' => array(
		'php' => 'PHP',
		'js'  => 'JavaScript',
	),
	'min'     => 1,
	'max'     => 5,
)

Properties

For Default Field Properties, see Field Types Definition.

Specific Properties

  • options (array|callable) — The available options for selection. Can be an associative array ('value' => 'Label'), an array of arrays with value and label keys, or a callable that returns options dynamically
  • options_key (string) — Optional: A key referencing a registered REST endpoint for fetching options asynchronously
  • async_params (array) — Optional: Additional parameters passed to the options callback. Supports dynamic value replacement using {{field_path}} placeholders
  • min (integer) — Optional: Minimum number of items
  • max (integer) — Optional: Maximum number of items
  • buttons (array) — Optional: Custom button labels (add, remove, duplicate)
  • disabled_buttons (array) — Optional: Buttons to disable (move, delete, duplicate)

Stored Value

The field stores an array of selected option values (strings) in the database:

array( 'php', 'js' )

Example Usage

Basic Multi Select

'product_tags' => array(
	'type'        => 'multi_select',
	'id'          => 'product_tags',
	'label'       => 'Product Tags',
	'description' => 'Select tags that apply to this product',
	'options'     => array(
		'new'      => 'New',
		'sale'     => 'Sale',
		'featured' => 'Featured',
		'limited'  => 'Limited Edition',
	),
	'default'     => array( 'new' ),
),

Multi Select with Array of Objects

'color_choices' => array(
	'type'    => 'multi_select',
	'id'      => 'color_choices',
	'label'   => 'Colors',
	'options' => array(
		array( 'value' => 'red', 'label' => 'Red' ),
		array( 'value' => 'green', 'label' => 'Green' ),
		array( 'value' => 'blue', 'label' => 'Blue' ),
	),
),

Multi Select with Dynamic Options

'country' => array(
	'type'    => 'multi_select',
	'id'      => 'country',
	'label'   => 'Countries',
	'options' => function ( array $args ): array {
		return array(
			'us' => 'United States',
			'ca' => 'Canada',
			'mx' => 'Mexico',
		);
	},
),

The callback receives an array with the following keys:

  • value: The current value of the field
  • search: The search term entered by the user
  • Additional parameters passed via async_params

Multi Select with Async Params

'product_type' => array(
	'type'    => 'select',
	'id'      => 'product_type',
	'label'   => 'Product Type',
	'options' => array(
		'physical' => 'Physical Product',
		'digital'  => 'Digital Product',
	),
),
'product_features' => array(
	'type'         => 'multi_select',
	'id'           => 'product_features',
	'label'        => 'Product Features',
	'options'      => 'get_product_features',
	'async_params' => array(
		'type' => '{{product_type}}',
	),
),

The async_params support dynamic value replacement using {{field_path}} placeholders, following the same path syntax as Conditions:

  • Dot notation for nested fields: {{parent_field.nested_field}}
  • # for relative references: {{#.sibling_field}}
  • Multiple # for parent levels: {{##.parent_sibling_field}}

cache_options (bool) — Optional

Defaults to true. When true, the async options list is fetched once and shared across all fields using the same options_key/async_params (the request does not include the field's value). Set to false to restore the legacy behavior where each field sends its value in the options request — needed only for callbacks whose async_params use dynamic {{field}} placeholders or that otherwise depend on value when returning the browse list.

Regardless of cache_options, labels of saved values are resolved separately from the browse list: server-side for storage-backed integrations (embedded in the page as a per-options_key value→label map), or via a batched resolve request in the block editor. In that call the callback receives value as an array of the value(s) to resolve. Server-side, async_params entries containing a {{field}} placeholder are dropped (their values are only known in the browser), so the callback gets the static params plus value and must be able to label a value from value alone. If it cannot, supply the labels yourself via the wpifycf_preresolved_options filter:

add_filter(
	'wpifycf_preresolved_options',
	function ( array $preresolved, array $by_key ) {
		foreach ( $by_key['my_terms'] ?? array() as $term_id ) {
			$term = get_term( (int) $term_id );

			if ( $term instanceof WP_Term ) {
				$preresolved['my_terms'][ $term_id ] = $term->name;
			}
		}

		return $preresolved;
	},
	10,
	2
);

$preresolved is the map of options_key => ( value => label ), $by_key the map of options_key => saved values; a third argument carries the prepared items.

Using Values in Your Theme

$product_tags = get_post_meta( get_the_ID(), 'product_tags', true );

if ( ! empty( $product_tags ) && is_array( $product_tags ) ) {
	$tag_labels = array(
		'new'      => 'New',
		'sale'     => 'Sale',
		'featured' => 'Featured',
		'limited'  => 'Limited Edition',
	);

	echo '<div class="product-tags">';
	foreach ( $product_tags as $tag ) {
		if ( isset( $tag_labels[ $tag ] ) ) {
			echo '<span class="product-tag product-tag--' . esc_attr( $tag ) . '">';
			echo esc_html( $tag_labels[ $tag ] );
			echo '</span>';
		}
	}
	echo '</div>';
}

With Conditional Logic

'has_variations' => array(
	'type'  => 'toggle',
	'id'    => 'has_variations',
	'label' => 'Product has variations?',
	'title' => 'Enable product variations',
),
'variation_attributes' => array(
	'type'       => 'multi_select',
	'id'         => 'variation_attributes',
	'label'      => 'Variation Attributes',
	'options'    => array(
		'color'    => 'Color',
		'size'     => 'Size',
		'material' => 'Material',
	),
	'conditions' => array(
		array( 'field' => 'has_variations', 'value' => true ),
	),
),

Field Factory

$f = new \Wpify\CustomFields\FieldFactory();

$f->multi_select(
	label: 'Tags',
	options: array( 'php' => 'PHP', 'js' => 'JavaScript' ),
	min: 1,
	max: 5,
);

Notes

  • The Multi Select field is based on React Select, providing a modern searchable dropdown
  • Selected options appear as chips/tags that can be individually removed
  • The field prevents duplicate selections
  • The stored value is always an array, even if only one option is selected
  • Options can be provided as a static array, a callable, or via async REST endpoints
  • Dynamic async_params allow creating dependent select fields where available options update based on other field values