Intro

Conditional Logic allows you to hide and show fields based on the values of other fields in the same context. For example, you may want to only show the "Background Image" field when the "Use background" checkbox has been checked.

When working with conditional logic, you will work with:

  1. Rules: A rule represents a single logical connection.
  2. Groups: A group represents multiple rules.

The relationship between the rules in a group is "AND", while the relationship between separate groups is "OR". This means that in order for a field to be displayed, at least one group must have all of its rules matched.

All of these rules and groups and rules are added to individual fields.

Example fields

Although you can use logic with a single checkbox, in order to understand how it works, we need to have an elaborate example.

Imagine that you are creating a vehicle catalog, with vehicles being a custom post type. Each vehicle would include those fields:

  1. Type is a radio, which has "New" and "Used" as options.
  2. Mileage is a number field, which is only shown when a vehicle has been marked as "used".
  3. Production year is another number field, which is only shown when a vehicle has been marked as "used".
  4. Insurance price would let editors enter an optional monthly insurance price. This field should only be visible for new cars and used cars, which have less than 10.000 miles and are 5 years old or newer.

In this case we have:

  • two simple rules for "Mileage" and "Production Year". Both of these fields are only shown for used vehicles.
  • two groups of rules for the "Insurance Price" field, which work independently:
    • The first group requires a car to be new.
    • The second group requires a car to be both newer than 5 years and to have less than 10k miles.

This example will be used to demonstrate both the usage in the interface, as well as in PHP.

Usage in the interface

All settings for conditional logic are located in the "Validation & Logic" tab when editing a field.

In order to enable conditional logic for the field, start by enabling the "Use conditional logic" checkbox. When you do so, you will see a new field, called "Conditional Logic". This is the place where you can define all needed rules.

Click the "+ Add Group" and you will be presented with a new group, which contains a single rule by default. You can add more rules and edit them. All options will change based on the type of the source field.

Usage in PHP

Conditional logic in PHP can be accessed by using the add_dependency and add_dependency_group methods.

add_dependency( $field, $value = null, $compare = null, $group = 0 )
add_dependency_group( $group = null )

What add_dependency does is to add a new rule to a group of rules. If there is no group specified when calling the method, it will add the rule to the last existing group. If there are no existing groups, the method will add a rule to the last one.

Calling add_dependency_group adds a new group to the field. If you do not specify a group (an instance of UF\Dependency\Group), an empty group will be added to the field. In both cases, calling add_dependency afterwards will add the new rules to this group.

If you call add_dependency_group without a specific group and do not add any rules to the field afterwards, the group will be ignored.

add_dependency

Arguments:
1. field must either be an UF\Field instance or simply the name of a field.
2. value is a value to compare against. The type of this parameter varies based on the comparator.
3. compare is a string, which defines which operator to use.

Comparators

Keyword/Identifier Description Operand type
Equality
= Equals Same as the field
== Equal Same as the field
!= Does not equal Same as the field
Mathematical
>= Greater than or equal to Numeric
<= Lesser than or equal to Numeric
< Lesser than Numeric
> Greater than Numeric
Relational
NOT_NULL Is not null when converted to a boolean -
NULL Is null when converted to a boolean -
IN In this list array
NOT_IN Not in this list array
CONTAINS The value is an array and contains the operand mixed
DOES_NOT_CONTAIN Does not contain mixed
CONTAINS_GROUP Contains (for repeater groups) string, the type of the group.
DOES_NOT_CONTAIN_GROUP Does not contain (for repeater groups) string, the type of the group.

An important note here is that if you are using a mathematical comparator, arrays will be converted to their count. This means that [ 'intro', 'gallery' ] will be seen by the conditional logic simply as 2.

Examples

$fields = array(
    // Show a field based on a checkbox
    Field::create( 'checkbox', 'show_background_image' ),
    Field::create( 'image', 'background_image' )
        ->add_dependency( 'show_background_image' ),

    // Show a field based on a specific value
    Field::create( 'select', 'shipping_method' )
        ->add_options(array(
            'store_pickup' => 'Store Pickup',
            'post'         => 'Post shipping',
        )),
    Field::create( 'select', 'pickup_store' )
        ->add_dependency( 'shipping_method', 'post' )
        ->add_options(array(
            'store_a' => 'Store A',
            'store_b' => 'Store B'
        )),

    // Show a field only when there are more than 3 images
    Field::create( 'gallery', 'images' ),
    Field::create( 'checkbox', 'enable_overlay' )
        ->add_dependency( 'images', 3, '>' ),

    // Use a relational comparator
    Field::create( 'multiselect', 'modules' )
        ->add_options(array(
            'intro',
            'gallery'    
        )),
    Field::create( 'textarea', 'intro_text' )
        ->add_dependency( 'modules', 'intro', 'CONTAINS' ),

    // Check if a specific group has been added to a repeater
    Field::create( 'repeater', 'content_blocks' )
        ->add_group( 'text', array(
            'fields' => array(
                Field::create( 'text', 'title' ),    
                Field::create( 'textarea', 'text' )    
            )    
        ))
        ->add_group( 'gallery', array(
            'fields' => array(
                Field::create( 'gallery', 'images' )
            )
        )),
    Field::create( 'select', 'gallery_type' )
        ->add_dependency( 'content_blocks', 'gallery', 'CONTAINS_GROUP' )
        ->add_options(array(
            'grid'   => 'Grid',
            'slider' => 'Slider'
        ))
);

add_dependency_group

This method allows you to add multiple groups of rules to a field. Once you call it, the field will switch to a new group for all following add_dependency calls.

Here is how the example with vehicles would look like:

$fields = array(
    Field::create( 'select', 'car_type' )
        ->add_options(array(
            'new'  => 'New Vehicle',
            'used' => 'User Vehicle',
        )),
    Field::crate( 'number', 'mileage' )
        ->add_dependency( 'car_type', 'used' ),
    Field::create( 'number', 'production_year' )
        ->add_dependency( 'car_type', 'used' ),

    Field::create( 'number', 'insurance_price' )
        ->add_dependency( 'car_type', 'new' )
        ->add_dependency_group()
        ->add_dependency( 'car_type', 'used' )
        ->add_dependency( 'mileage', 10000, '<' )
        ->add_dependency( 'production_year', date( 'Y' ) - 5, '>=' )
);

As you can see, initially we work with the default group of rules for the fields, but we create a new one by calling add_dependency_group. This way, the first rule is contained in a single group, while next three are separated.

Because groups have a boolean OR relationship and fields inside them have a boolean AND, the insurance field will be only shown based on the matches in the first rule OR all rules in the second group.

If this logic was written as a PHP condition with every field having its own variable, it would look like this:

$insurance = (
    ( 'new' == $type )
    ||
    ( 'used' == $type && $mileage < 10000 && $production_year >= ( date( 'Y' ) - 5 ) )
);

Accessing parent levels

If you need to access a value, which is not in the direct context of the current field, you can prepend '../' to the first parameter of add_dependency to get one level up.

<?php
$fields = array(
    Field::create( 'select', 'header_type' )
        ->add_options(array(
            'simple' => 'Simple',
            'slider' => 'Image Slider',
        )),

    Field::create( 'repeater', 'content_blocks' )
        ->add_group( 'image', array(
            Field::create( 'image', 'image' ),
            Field::create( 'checkbox', 'include_in_slider' )
                ->add_dependency( '../header_type', 'slider' )
        ))
);

This feature is only accessible in fields, which contain other fields:

  • In repeater field groups
  • In layout field groups
  • In complex fields

You can also use ../ multiple times in order to get up multiple levels of nesting.