By lincoln-batsirayi on
I'm creating some additional functionality for a module and as a part of that I'd like to use the form state API to conditionally show and hide some elements. I've been able to toggle the visibility of a textfield using a select field but when i attempt to do the same for a datetime or table select field, it doesn't work and I'm sure why. Here's my code:
$form['duration'] = [
'#type' => 'select',
'#title' => t('Lifetime'),
'#options' => [
60 => t('@days Days', ['@days' => 1]),
172800 => t('@days Days', ['@days' => 2]),
345600 => t('@days Days', ['@days' => 4]),
604800 => t('@days Days', ['@days' => 7]),
1209600 => t('@days Days', ['@days' => 14]),
-1 => t('Unlimited'),
'other' => t('Custom'),
],
'#default_value' => '',
'#attributes' => [
'id' => 'edit-duration',
],
];
// Elements inside container are hidden by default and are shown when other
// is selected from the select list above.
$form['container'] = [
'#type' => 'container',
'#states' => [
'visible' => [
'[name="duration"]' => ['value' => 'other'],
],
],
];
// todo:// Add today's date as default if one doesn't exist in config.
$form['container']['expiration'] = [
'#type' => 'datetime',
'#title' => $this->t('Content expiration'),
'#default_value' => DrupalDateTime::createFromTimestamp($config->get('custom_date')),
];
$bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo('node');
$options = $defaults = [];
foreach ($bundles as $bundle_id => $bundle) {
$options[$bundle_id] = [
'title' => ['data' => ['#title' => $bundle['label']]],
'type' => $bundle['label'],
];
}
$selected_types = $config->get('selected_content_types');
foreach ($selected_types as $key => $type) {
$defaults[$type] = TRUE;
}
if (!empty($options)) {
$form['container']['bundles'] = [
'#type' => 'tableselect',
'#header' => [
'type' => 'Content types',
],
'#options' => $options,
'#default_value' => $defaults,
'#attributes' => [
'class' => [
'no-highlight'
],
],
];
$form['bundles']['#attributes']['class'][] = 'content-type-table';
}any help/tips would be greatly appreciated, thanks in advance !
UPDATE: I've now update code so that both the elements i want to hide are inside a container and I've added the states visible property on the container as per wombatbuddy's comment and it works.
Comments
It's almost always a bad idea
It's almost always a bad idea to set the name attribute in Drupal forms. It leads to unexpected consequences.
Leave the name as it is, and either use a class on the element for your selector, or use the default name set by Drupal.
Contact me to contract me for D7 -> D10/11 migrations.
Oh, Didn't know that, I've
Oh, Didn't know that, I've updated it to use the default name. Thank you. Unfortunately the issue persists...
You need to update the code
You need to update the code in the original post then.
Contact me to contract me for D7 -> D10/11 migrations.
Oh yh of course, my bad. Done
Oh yh of course, my bad. Done.
Have you verified this
Have you verified this element exists:
Contact me to contract me for D7 -> D10/11 migrations.
Yes i have and it does indeed
Yes i have and it does indeed it's the one generated by drupal from the form element creation of the duration select element.
Just put them in a container,
Just put them in a container, like this:
Omg yes, that worked ! Thank
Omg yes, that worked ! Thank you so much ! Now to understand the issue, do states only work certain elements?
Well, they only don't work on
Well, they only don't work on a few elements. It depends on how the template for that element outputs its attributes. I'd run into this issue with other element types in the past (which I don't recall off the top of my head, and may have even been a datettime), but it works for nearly all element types.
Contact me to contract me for D7 -> D10/11 migrations.