Form states

Drupal Form API State

About Conditional Form Fields in Drupal you can read here. In this article I would like share some ready to use examples.

In general the structure of #states looks like it:

<?php

$form['some_field']['#states'] => [
  'state_type' => [
    'selector' => 'conditions',
    'selector' => 'conditions',
  ],
];

So, let's go to examples:

<?php

$form['show_name'] = [
  '#type' => 'checkbox',
  '#title' => t('Show name?'),
];

// Hide "name" field when the "show_name" checkbox is checked.
$form['name'] = [
  '#type' => 'textfield',
  '#title' => t('Name'),
  '#states' => [
    'visible' => [
      ':input[name="show_name"]' => ['checked' => TRUE],
    ],
  ],
];
<?php

// Show the email field when the "email" is selected and the "name" field is filled.
$form['email'] = [
  '#type' => 'textfield',
  '#title' => t('Email'),
  '#states' => [
    'visible' => [
      ':select[name="method"]' => ['value' => 'email'],
      ':input[name="name"]' => ['filled' => TRUE],
    ],
  ],
];
<?php

// Show the "email" field when either:
// * Anonymous is checked and method is email
// OR
// * The "name" is filled and the method is email
$form['email'] = [
  '#type' => 'textfield',
  '#title' => t('Email'),
  '#states' => [
    'visible' => [
      [
        ':input[name="anonymous"]' => ['checked' => TRUE],
        ':select[name="method"]' => ['value' => 'email'],
      ],
      [
        ':input[name="name"]' => ['filled' => TRUE],
        ':select[name="method"]' => ['value' => 'email'],
      ],
    ],
  ],
];
<?php

// Show the email field when either condition is TRUE, but not both
// * Anonymous is checked and method is email
// * The "name" is filled and the method is email
$form['email'] = [
  '#type' => 'textfield',
  '#title' => t('Email'),
  '#states' => [
    'visible' => [      
        ':input[name="anonymous"]' => ['checked' => TRUE],
        ':select[name="method"]' => ['value' => 'email'],
      ],
      'xor',
      [
        ':input[name="name"]' => ['filled' => TRUE],
        ':select[name="method"]' => ['value' => 'email'],
      ],
    ],
  ],
];
<?php

$form['first_name'] = [
  '#type' => 'textfield',
  '#title' => t('First Name'),
];

// Make "last_name" required if "first_name" is filled.
$form['last_name'] = [
  '#type' => 'textfield',
  '#title' => t('Last Name'),
  '#states' => [
    'required' => [
      ':input[name="first_name"]' => ['filled' => TRUE],
    ],
  ],
];

Also, you can use for select wildcard selectors (*, ^ and $) like CSS for classes like this:

<?php

$form['first_name'] = [
  '#type' => 'textfield',
  '#title' => t('First Name'),
];

// Make "last_name" required if any field ends with "_name" is filled.
$form['last_name'] = [
  '#type' => 'textfield',
  '#title' => t('Last Name'),
  '#states' => [
    'required' => [
      ':input[name$="_name"]' => ['filled' => TRUE],
    ],
  ],
];

The following states may be applied to an element:

  • enabled
  • disabled
  • required
  • optional
  • visible
  • invisible
  • checked
  • unchecked
  • expanded
  • collapsed

The following states may be used in remote conditions:

  • empty
  • filled
  • checked
  • unchecked
  • expanded
  • collapsed
  • value

The following states exist for both elements and remote conditions, but are not fully implemented and may not change anything on the element:

  • relevant
  • irrelevant
  • valid
  • invalid
  • touched
  • untouched
  • readwrite
  • readonly