- π¦πΊAustralia larowlan π¦πΊπ.au GMT+10
I think you can make this work in a specific use case by adding 'form_element' to $element['#theme_wrappers'] where $element is a table.
Moving to a feature request.
When a form contains a table, that table does not properly handle the #states
property. As a workaround, the table can be wrapped in a container
element type, but that shouldn't be necessary.
In digging into the code, it appears that FormHelper::processStates()
gets invoked for all render elements, including tables, and the <table>
HTML element is rendered with a data-drupal-states
HTML attribute. In addition, states.js
does process the behavior and sets up all the triggers. It seems like the issue is that states.js
uses jQuery to find the nearest '.js-form-item, .js-form-submit, .js-form-wrapper'
wrapper around the table, which it does not find. This causes the behavior not to work.
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class SomeForm extends FormBase {
public function getFormId(): string {
return 'repro_form';
}
public function buildForm(array $form,
FormStateInterface $form_state): array {
$form['required'] = [
'#type' => 'checkbox',
'#title' => $this->t('Check me'),
'#default_value' => FALSE,
];
$form['some_textfield'] = [
'#type' => 'textfield',
'#title' => $this->t('Some field'),
'#states' => [
'invisible' => [
':input[name="required"]' => [
'checked' => TRUE,
],
],
],
];
$contacts_table = $this->buildContactsTable();
$contacts_table['#states'] = [
'invisible' => [
':input[name="required"]' => [
'checked' => TRUE,
],
],
];
$form['contacts'] = $contacts_table;
$form['contacts_wrapper'] = [
'#type' => 'container',
'#states' => [
'invisible' => [
':input[name="required"]' => [
'checked' => TRUE,
],
],
],
'contacts' => $contacts_table,
];
return $form;
}
protected function buildContactsTable(): array {
$table = [
'#type' => 'table',
'#caption' => $this->t('Sample Table'),
'#header' => [
$this->t('Name'),
$this->t('Phone'),
],
];
for ($i = 1; $i <= 4; $i++) {
$table[$i]['name'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#title_display' => 'invisible',
];
$table[$i]['phone'] = [
'#type' => 'tel',
'#title' => $this->t('Phone'),
'#title_display' => 'invisible',
];
}
return $table;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
// Do nothing for this sample.
}
}
some.form:
path: '/admin/some-form'
defaults:
_form: '\Drupal\my_module\Form\SomeForm'
_title: 'Demonstrate bugs'
requirements:
_access: 'TRUE'
/admin/some-form
All the form elements except the checkbox should hide, but the unwrapped table does not.
Either tables should be wrapped automatically by some class that states.js
recognizes, or states.js
should not require a wrapper element to do its work.
Active
11.0 π₯
Last updated
Affects the content, performance, or handling of Javascript.
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.
I think you can make this work in a specific use case by adding 'form_element' to $element['#theme_wrappers'] where $element is a table.
Moving to a feature request.