You are here

function drupal_process_states in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/includes/common.inc \drupal_process_states()

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

A "state" means a certain property on a DOM element, such as "visible" or "checked". A state can be applied to an element, depending on the state of another element on the page. In general, states depend on HTML attributes and DOM element properties, which 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:


array(
  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:

array(
  '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:


array(
  'visible' => array(
    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:

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

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

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

Parameters

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

See also

form_example_states_form()

1 call to drupal_process_states()
Renderer::doRender in core/lib/Drupal/Core/Render/Renderer.php
See the docs for ::render().

File

core/includes/common.inc, line 574
Common functions that many Drupal modules will need to reference.

Code

function drupal_process_states(&$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']);
}