Flexible Content Fields in Field Manager

Field Manager doesn’t have a flexible content field type as Advanced Custom Fields Pro does, but it is possible to mimic the functionality by using a little logic.

First, we need a parent field group, which is repeatable so we can add multiple content sections, and sortable so we can rearrange the content sections by dragging and dropping them:

$fm = new Fieldmanager_Group( [
	'name' => 'flexible-content',
	'label' => __( 'Content Section', 'your-textdomain' ),
	'limit' => 0,
	'sortable' => 1,
	'add_more_label' => __( 'Add Content Section', 'your-textdomain' ),
] );

To this field group, we’ll add a select field. This select field will later be populated with the names of all our flexible content fields’ labels, so we can select which type of content section we want to use:

$flexible_content_select = new Fieldmanager_Select( __( 'Section Type', 'your-textdomain' ), [ 'name' => 'section_type' ] );
$fm->add_child( $flexible_content_select );

Next, we’ll initialize an array, which will hold all of our flexible content fields – or field groups as they really are:

$flexfields = [];

Now, we can add as many regular field groups as we like to this array:

// Add a flexible content field.
$flexfields[] = new Fieldmanager_Group( [
	'name' => 'demo-group',
	'label' => __( 'Demo Section', 'your-textdomain' ),
	'children' => [
		'field-one' => new Fieldmanager_TextField( __( 'First Field', 'your-textdomain' ) ),
		'field-two' => new Fieldmanager_TextField( __( 'Second Field', 'your-textdomain' ) ),
	],
] );

// Add another flexible content field.
$flexfields[] = new Fieldmanager_Group( [
	'name' => 'youtube',
	'label' => __( 'YouTube Video', 'your-textdomain' ),
	'children' => [
		'youtube-url' => new Fieldmanager_TextField( __( 'YouTube URL', 'your-textdomain' ) ),
		'preview-image' => new Fieldmanager_Media( __( 'Preview Image', 'your-textdomain' ), [
			'preview_size' => 'medium',
		] ),
	],
] );

After we have added all our field groups to the flexible content field array, we’ll loop through it to add the field groups name/labels to the select field, modify the field groups to only show if they are selected in the select field and finally add them to the parent field group:

foreach ( $flexfields as $flexfield ) {
	// Add the flexible content field to the select field.
	$flexible_content_select->add_options( [ $flexfield->name => $flexfield->label ] );

	// Modify the field group to only display if the field type is selected.
	$flexfield->display_if = [ 'src' => 'section_type', 'value' => $flexfield->name ];

	// Add the flexible content field to the parent field group.
	$fm->add_child( $flexfield );
}

$fm->add_meta_box( __( 'Flexible Content', 'your-textdomain' ), 'post' );

If you edit a post now, you should have a metabox where you can add content sections and select the content type you want to show:

Select a flexible content field type.
Select a flexible content field type …
… and the field group for the content type will show.

Here is the full code which mimics an ACF flexible content field in Field Manager. This code also add a title field for each section, and a section which shows all the fields available from Field Manager:

A final warning

Even though the fields from the inactive field groups aren’t visible – they’re still there, unlike the real flexible content fields in ACF Pro. This means that if you are a heavy flexible content user, you might run into scaling issues. Many times I’ve seen sites with ~15 different flexible content fields and pages which use way more that 15 content sections. If those flexible content fields have 5 data fields on average, you’ll end up with more than 1350 data fields in total. Field Manager will then store all those data fields in a single serialized field in the postmeta table.