Problem/Motivation

I have added field conditions in my project using states. I have textfields that are depending on entity reference fields being filled before the textfields are shown. After changes done in issue https://www.drupal.org/project/drupal/issues/3347144 these field conditions do not work anymore. When entity reference field value is filled, the visible state is not anymore triggered on the dependent field.

Steps to reproduce

Create a content type and add there a text field and an entity reference field (mine is used to reference Media).

Create a custom module and in the .module file, add a visible state to a textfield with field_widget_single_element_form_alter -hook. In this case the textfield machine name is 'field_image_caption_short' and the entity referend field is 'field_main_media'.

function test_conditional_fields_field_widget_single_element_form_alter(&$element, &$form_state, $context): void {

  $field_definition = $context['items']->getFieldDefinition();
  $field_name = $field_definition->getName();

  if ($field_name !== 'field_image_caption_short') {
    return;
  }

  // Create a selector for the "depended_field" field.
  $fieldSelector = sprintf(':input[name="%s[%s]"]', 'field_main_media', 'target_id');

  // Alter the widget state.
  $element['value']['#states'] = [
    'visible' => [
      $fieldSelector => ['filled' => TRUE],
    ],
  ];
}

I have checked that the element names are still correct so the state change should work. State change also works when having the textfield be dependent on another textfield.

Issue fork drupal-3416398

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

thatguy created an issue. See original summary.

cilefen’s picture

Are there console errors? Be sure to test with the 10.2.x branch as there are JavaScript fixes on it.

thatguy’s picture

There are no console errors and I have tested this with a clean 10.2.3-dev setup as well and the issue is present there too

stockticker’s picture

+1. In my case, it's:

$form["submit"]['#states'] = [
        'disabled' => [
          ':input[name="file_upload[fids]"]' => ['empty' => TRUE],
        ],
      ];

it stopped working after upgrading to 10.2.2.

hablat’s picture

StatusFileSize
new444 bytes

We're running into this issue ourselves.

Narrowed it down to the following line in core/misc/states.js changing from
const $states = $(context).find('[data-drupal-states]');
to
const elements = once('states', '[data-drupal-states]', context);
due to the the fix in
https://www.drupal.org/project/drupal/issues/3347144

We have a temporary fix at the moment with a custom patch that changes
const elements = once('states', '[data-drupal-states]', context);
back to
const elements = $(context).find('[data-drupal-states]');

We're using this until someone comes up with a better patch.

lpeabody’s picture

This is one of those things where it would be nice for Drupal core maintainers to come up with JS contracts similar to the way they have developed Interface contracts for swappable Symfony services and public data members and functions.

We ran into a similar issue where we are dependent on Facets checkbox list selections to determine state of a form element on the page. The state logic lives on the form element, so every time Facets re-creates its blocks via AJAX we need to rerun the States API behaviors on the form element. This stopped working after the previously mentioned Core update to the States API.

Before

1. Page loads.
2. Form button is default disabled (becomes enabled if one of three Facets checkbox list blocks contains any checked elements).
3. Facets blocks initially loaded with list of links (Facets later transforms these to checkboxes in custom JavaScript https://git.drupalcode.org/project/facets/-/blob/2.0.x/js/checkbox-widge...).
4. Facet behavior checkbox JS runs and converts links into checkboxes for each checkbox widget block on page. Part off this behavior invokes Drupal.attachBehaviors for each instance of the converted Facet block, passing the Facets checkbox list block as the context, along with Drupal.settings.
5. In our custom JS, we have a behavior whose attach function looks at the context and determines if it was a facet checkbox list, and if it is then it re-runs Drupal.attachBehaviors() to ensure that the States API re-applies state information on the form element who has these checkbox value depenencies.

Workaround to account for new once usage in States API

Our workaround was to remove the added once attribute on the pertinent form element, which might be how this needs to be handled going forward.

1. Page loads.
2. Form button is default disabled (becomes enabled if one of three Facets checkbox list blocks contains any checked elements).
3. Facets blocks initially loaded with list of links (Facets later transforms these to checkboxes in custom JavaScript https://git.drupalcode.org/project/facets/-/blob/2.0.x/js/checkbox-widge...).
4. Facet behavior checkbox JS runs and converts links into checkboxes for each checkbox widget block on page. Part off this behavior invokes Drupal.attachBehaviors for each instance of the converted Facet block, passing the Facets checkbox list block as the context, along with Drupal.settings.
5. In our custom JS, we have a behavior whose attach function looks at the context and determines if it was a facet checkbox list, and if it is then it first removes the data-once value that was added to the form element, then it re-runs Drupal.attachBehaviors() to ensure that the States API re-applies state information on the form element who has these checkbox value dependencies.

I couldn't find a better, documented way to handle this situation. I feel at the very least the bugfix issue (https://www.drupal.org/project/drupal/issues/3347144) could use a change record to indicate what changed and why it changed, and perhaps also document workarounds to account for the changes given the use-cases presented in this issue.

attheshow’s picture

+1 for patch in #5.

Our form states were broken as well after upgrading to 10.2.2 today.

catch’s picture

catch’s picture

Status: Active » Fixed

Thanks for the reports. I've reverted #3347144: Form API #states property/states should use .once() to apply its rules (Can cause failures with BigPipe and possibly other situations) and re-opened that issue, closing this issue as fixed - we can continue on the bug found here over there. The revert will be included in the next 10.2.x patch release.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

alexander tallqvist made their first commit to this issue’s fork.

alexander tallqvist’s picture

Version: 10.2.x-dev » 10.3.x-dev
StatusFileSize
new555 bytes

Still experiencing the same problem @thatguy described when running Drupal 10.3.2. The patch provided in #5 seems to fix the issue. Re-rolling the same patch for 10.3.2.

nod_’s picture

a proper fix is in the works for core, could you test #3468860: JS #states behavior does not have a detach method. It should fix this but introduces another change in that #states about a missing element are now applied, they used to be ignored.