Skip to content

Complex

Radoslav Georgiev edited this page Oct 21, 2018 · 4 revisions

Purpose

The Complex field allows you to group multiple simple fields within a single field. This gives you the flexibility to to:

  • Reuse all of the fields from an existing container
  • Improve your fields visually by combining the "rows" and "grid" layouts.
  • Save the sub-fields of the complex field both as nested fields, as well as top-level fields.

complex-field

Options

Adding and loading fields

You add new fields to the Complex field, but you can also load an existing container.

Adding new fields

In the interface adding fields is very straight-forward: it works the same way as adding fields to containers. Click "+ Add Field" and follow the instructions here.

In PHP you can use the add_fields method of the field, which works the same way as that of a container:

Field::create( 'complex', 'complex_field' )
	->add_fields(array(
		Field::create( 'text', 'sub_field_a' ),
		Field::create( 'text', 'sub_field_b' )
	));

Using existing fields

The Complex field allows you to use the fields of an existing container. This is very useful when you have a set of fields, which you need to use in multiple places, ex. the fields, which define a button.

In the interface, select "Load a container" in the "Field source" field. Then choose the container in the "Source Container" field.

In PHP use the load_from_container( $id ) method. $id should be the ID of a container, which has already been created.

<?php
use Ultimate_Fields\Container;
use Ultimate_Fields\Field;

Container::create( 'button_fields' )
	->add_fields(array(
		Field::create( 'text', 'text', 'Text' )
			->set_width( 40 ),
		Field::create( 'link', 'link', 'Link' )
			->set_width( 60 ),
		Field::create( 'select', 'type', 'Type' )
			->input_type( 'radio' )
			->set_orientation( 'horizontal' )
			->set_width( 50 )
			->add_options(array(
				'standard' => 'Standard',
				'primary'  => 'Primary'
			)),
		Field::create( 'icon', 'icon', 'Icon' )
			->set_width( 50 )
	));

Container::create( 'teaser' )
	->add_location( 'post_type', 'post' )
	->add_fields(array(
		Field::create( 'complex', 'button' )
			->load_from_container( 'button_fields' )
	));

As you can see, you can create a container even without associating it with any locations (the button_fields container). Then by using the ID of that container, you can easily use all of its fields to a complex field.

Saving values

When saving the values of a complex field's sub-fields, you have two options:

  • Save sub-values as an array (default): All values will be put into an array and saved as a single value in the database.
  • Merge sub-fields into the parent level: The values will be saved transparently, as if the sub-fields were replacing the complex field.

If you are using the Complex field just in order to improve the layout of fields, merging them with the parent is probably the better option. When you are using this mode, you can also set a custom prefix for the fields. If you use button_ as prefix, text will be automatically saved as button_text.

If you are considering the possiblity to add the same sub-fields to two or more complex fields in the same context, it is a better idea not to merge them. This way you would be able to use the same code for displaying them. Please scroll down to Usage for more details.

In PHP, if you'd like to save the values as an array, you do not have to call any additional methods. If you want to merge them however, you should use the merge( $prefix = null ) method of the complex field. It allows you to both merge the values, as well as optionally setting a prefix.

Container::create( 'teaser' )
	->add_fields(array(
		// Simply merge
		Field::create( 'complex', 'button' )
			->load_from_container( 'button_fields' )
			->merge(),

		// Add prefixes
		Field::create( 'complex', 'left_button' )
			->load_from_container( 'button_fields' )
			->merge( 'left_button_' ),
		Field::create( 'complex', 'left_button' )
			->load_from_container( 'button_fields' )
			->merge( 'right_button_' ),
	));

Layout

As with containers, you can use both "Grid" and "Rows" as layouts for the fields within a complex field.

In the interface, simply select the "Layout", which you would like to use.

In PHP the default layout is always grid. If you prefer using rows, you can call the rows_layout method:

Field::create( 'complex', 'button_fields' )->rows_layout()->add_fields(/* ... */)

Usage

The usage of the complex field depends on the saving mode that you have selected.

Merged values

If you have merged the values of a complex field with its parent, you can access them by simply using the field name, eventually prefixed:

<a href="#"><?php the_value( 'button_text' ) ?></a>

For this example we assumed that there is a text sub-field within a complex field, whose values are merged with a button_ prefix.

Array values

When values are saved as an array, their usage is very similar to the one of a Repeater Field's values.

You have to use the have_groups function with the name of the complex field. Then you can use get_sub_value, the_sub_value and etc.

As an example, let's use a container which uses button_fields (declared above) twice within two separate complex fields:

Container::create( 'teaser' )
	->add_location( 'post_type', 'post' )
	->add_fields(array(
		Field::create( 'complex', 'left_button' )
			->load_from_container( 'button_fields' ),
		Field::create( 'complex', 'right_button' )
			->load_from_container( 'button_fields' )
	));

Now, let's create a file called button.php in the root of your theme, which we will use for buttons throughout the theme:

<a href="<?php the_sub_value( 'link' ) ?>" class="button-<?php the_sub_value( 'type' ) ?>">
	<?php the_sub_value( 'icon' ) ?>
	<?php the_sub_value( 'text' ) ?>
</a>

Now within your single.php file you can use the button wherever you need to by calling get_template_part( 'button' ):

<div class="alignleft">
	<?php while( have_groups( 'left_button' ) ): the_group() ?>
		<?php get_template_part( 'button' ) ?>
	<?php endwhile ?>
</div>

<div class="alignright">
	<?php while( have_groups( 'right_button' ) ): the_group() ?>
		<?php get_template_part( 'button' ) ?>
	<?php endwhile ?>
</div>

The example works because once you have entered a have_group - the_group loop, all *_sub_value functions work directly with the name of the sub-field. And considering that both left_button and right_button have the same sub-fields, we can easily use the same template for displaying their values.

Clone this wiki locally