function FormHelper::processStates

Same name in other branches
  1. 9 core/lib/Drupal/Core/Form/FormHelper.php \Drupal\Core\Form\FormHelper::processStates()
  2. 8.9.x core/lib/Drupal/Core/Form/FormHelper.php \Drupal\Core\Form\FormHelper::processStates()
  3. 10 core/lib/Drupal/Core/Form/FormHelper.php \Drupal\Core\Form\FormHelper::processStates()

Adds JavaScript to change the state of an element based on another element.

A "state" means a certain property of a DOM element, such as "visible" or "checked", which depends on a state or value of another element on the page. In general, states are HTML attributes and DOM element properties, which are applied initially, when page is loaded, depending on elements' default values, and then may change due to user interaction.

Since states are driven by JavaScript only, it is important to understand that all states are applied on presentation only, none of the states force any server-side logic, and that they will not be applied for site visitors without JavaScript support. All modules implementing states have to make sure that the intended logic also works without JavaScript being enabled.

#states is an associative array in the form of:


[
  STATE1 => CONDITIONS_ARRAY1,
  STATE2 => CONDITIONS_ARRAY2,
  ...
]

Each key is the name of a state to apply to the element, such as 'visible'. Each value is a list of conditions that denote when the state should be applied.

Multiple different states may be specified to act on complex conditions:

[
    'visible' => CONDITIONS,
    'checked' => OTHER_CONDITIONS,
];

Every condition is a key/value pair, whose key is a jQuery selector that denotes another element on the page, and whose value is an array of conditions, which must bet met on that element:


[
  'visible' => [
    JQUERY_SELECTOR => REMOTE_CONDITIONS,
    JQUERY_SELECTOR => REMOTE_CONDITIONS,
    ...
  ],
]

All conditions must be met for the state to be applied.

Each remote condition is a key/value pair specifying conditions on the other element that need to be met to apply the state to the element:

[
    'visible' => [
        ':input[name="remote_checkbox"]' => [
            'checked' => TRUE,
        ],
    ],
];

For example, to show a textfield only when a checkbox is checked:

$form['toggle_me'] = [
    '#type' => 'checkbox',
    '#title' => t('Tick this box to type'),
];
$form['settings'] = [
    '#type' => 'textfield',
    '#states' => [
        // Only show this field when the 'toggle_me' checkbox is enabled.
'visible' => [
            ':input[name="toggle_me"]' => [
                'checked' => 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

When referencing select lists and radio buttons in remote conditions, a 'value' condition must be used:


  '#states' => [
    // Show the settings if 'bar' has been selected for 'foo'.
    'visible' => [
      ':input[name="foo"]' => ['value' => 'bar'],
    ],
  ],

Parameters

array $elements: A render array element having a #states property as described above.

See also

\Drupal\form_test\Form\JavascriptStatesForm

\Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest

3 calls to FormHelper::processStates()
FormHelperTest::testProcessStates in core/tests/Drupal/Tests/Core/Form/FormHelperTest.php
@covers ::processStates @dataProvider providerElements
Link::preRenderLink in core/lib/Drupal/Core/Render/Element/Link.php
Pre-render callback: Renders a link into #markup.
Renderer::doRender in core/lib/Drupal/Core/Render/Renderer.php
See the docs for ::render().

File

core/lib/Drupal/Core/Form/FormHelper.php, line 205

Class

FormHelper
Provides helpers to operate on forms.

Namespace

Drupal\Core\Form

Code

public static function processStates(array &$elements) {
    $elements['#attached']['library'][] = 'core/drupal.states';
    // Elements of '#type' => 'item' are not actual form input elements, but we
    // still want to be able to show/hide them. Since there's no actual HTML
    // input element available, setting #attributes does not make sense, but a
    // wrapper is available, so setting #wrapper_attributes makes it work.
    $key = $elements['#type'] == 'item' ? '#wrapper_attributes' : '#attributes';
    $elements[$key]['data-drupal-states'] = Json::encode($elements['#states']);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.