At one of the recent Drupal Camps (Donetsk, I guess, it was) someone mentioned #states. As I personally had never come across one, only heard of them, I decided to dig into the issue and share my observations with you (as this topi will be useful for every Drupal developer, I guess).
So, what kind of feature is it?
# States keeps adding JavaScript that prompts changing the state of one element based on the state of another, after a user action's occurred.
What does it do?
Originally, #states was meant to prompt creating dynamic forms. A simple example: here we have a form with radio buttons "Job Search" and "Employer", while different values are being chosen, the user is displayed various elements of the form for filling.
What exactly can be done using the #states?
Everything can be done without a single line of JavaScript, only the PHP, only the Drupal Form API.
Thus, let's consider a basic example:
'# States' => array (
STATE1 => CONDITIONS_ARRAY1,
STATE2 => CONDITIONS_ARRAY2,
...
)
here:
STATE1, STATE2 - a condition that must be applied to the element
CONDITIONS_ARRAY1, CONDITIONS_ARRAY2 - sets of conditions under which a property should be used.
Sets of conditions are specified in an array mode whereby the key being the Jquery selector for any other element on the page (not obligatory restricted to the current form), and the value being a set (as well as a php array) of properties of this element, given the coincidence between the above we need to apply to the initial state of the element STATE1, namely:
‘#states’ => array(
STATE1 => array(
JQUERY_SELECTOR1 => array(
REMOTE_CONDITION1 => REMOTE_VALUE1,
REMOTE_CONDITION2 => REMOTE_VALUE2,
),
JQUERY_SELECTOR2 => array(
REMOTE_CONDITION3 => REMOTE_VALUE3,
REMOTE_CONDITION4 => REMOTE_VALUE4,
),
),
STATE2 => array.......
)
The next question that I needed to find the answer for was about the types of properties that were supported?
List of states (STATE1, STATE2 in the example above) that can be used for the element:
enabled
- disabled
- required
- optional
- visible
- invisible
- checked
- unchecked
- expanded
- collapsed
Here is the list of conditions (REMOTE_CONDITION1, REMOTE_CONDITION2 in the example above) which can be used for the items that are specified with use of Jquery selectors:
empty
- filled
- checked
- unchecked
- expanded
- collapsed
- value
The following list of states can be used for both types of elements (and STATE1, and REMOTE_CONDITION1), but according to the documentation, they have not yet been fully realized, and their utilization won't bring about any changes to the elements:
relevant
- irrelevant
- valid
- invalid
- touched
- untouched
- readwrite
- readonly
And you are welcome: here's some more 'real world' example of usage.
A short note
At the moment there is no possibility to use a set of conditions (REMOTE_CONDITION1, REMOTE_CONDITION2 ...), method OR. If you have such need, you can use AJAX Forms.
That kind of the implementation of the #states is completely tied to JavaScript, it should be understood that it bears no server-side logic, only an interface for the end users. And it wouldn’t work with a disabled JavaScript in your browser. It means you have to do something to make sure that all functional works correctly without JavaScript, as it is.
Useful links
1) https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_process_states/7
2) https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#states
3) https://www.drupal.org/project/examples