Can Drupal 8 Form #states API be used to expand/collapse <details>
-
21-01-2021 - |
Question
Given a checkbox field with two options:
- "Closed" (selected by default)
- "Open"
I'd like to expand or collapse the <details>
container of a different field (in our specific case an Address field). In HTML terms, this means adding the open
HTML5 attribute to the <details>
tag and adding aria-expanded=true
to the <summary>
tag when the "Open" radio button value is clicked, and ensure it is removed when that radio option is not selected (which means by default at page load time as well).
I've found a few older semi-related issues and the documentation page for Drupal 8's drupal_process_states
, but it's looking like this isn't possible with the Form #states
API in Drupal 8. The docs do not include "open" in the list of valid states that may be applied to an element.
The valid states are:
- enabled
- disabled
- required
- optional
- visible
- invisible
- checked
- unchecked
- expanded
- collapsed
One would think that maybe the expanded
and collapsed
options could work, however this does not seem to be the case with my sample code below:
function mymodule_form_node_<type>_form_alter(&$form, FormStateInterface $form_state) {
$form['field_address']['#states'] = [
// Expand address field container when the Trigger field is 'Open'.
'expanded' => [
':input[name="field_trigger"]' => [
'value' => 'open'
],
],
];
}
Replacing 'expanded' state with 'open' in the above does not work, nor does the inverse logic using 'collapsed' state work:
function mymodule_form_node_<type>_form_alter(&$form, FormStateInterface $form_state) {
$form['field_address']['#states'] = [
// Collapse address field container when the Trigger field is 'Closed'.
'collapsed' => [
':input[name="field_trigger"]' => [
'value' => 'closed'
],
],
];
}
No correct solution
OTHER TIPS
Rather than using expanded/collapsed use open/close like below:
function mymodule_form_node_<type>_form_alter(&$form, FormStateInterface $form_state) {
$form['field_address']['#states'] = [
// Expand address field container when the Trigger field is 'Open'.
'open' => [
':input[name="field_trigger"]' => [
'value' => 'open'
],
],
'close' => [
':input[name="field_trigger"]' => [
'value' => 'closed'
],
],
];
}
Unfortunately, I'm going to answer my own question: expanded
and collapsed
states do work for the <details>
type.
My problem was operator error. I was adding the #states
array at the level of the '#type' => 'container'
but the container has a widget inside of it that holds the '#type' => 'details'
. Fun times with Form API!
The working code is this:
<?php
// In mymodule.module
use \Drupal\Core\Form\FormStateInterface;
function mymodule_form_node_<type>_form_alter(&$form, FormStateInterface $form_state) {
$form['field_address']['widget'][0]['#states'] = [
// Expand location field when the Type is 'On-site'.
'expanded' => [
':input[name="field_trigger"]' => [
'value' => 'open'
],
],
// Collapse location field when the Type is 'Online'.
'collapsed' => [
':input[name="field_trigger"]' => [
'value' => 'closed'
],
],
];
// Load edit form with Location field either open or closed, based
// on the value of the Trigger field.
$form['field_address']['widget'][0]['#open'] = ($form['field_trigger']['widget']['#default_value'] == 'open') ? 1 : 0;
}