Problem/Motivation

#994360: #states cannot check/uncheck checkboxes elements included a change to no longer set the disabled property of the targeted element directly, since it should be included by .closest('.js-*').find() (which will target both individual elements or groups with the same code).

However, the find() doesn't include all the HTML elements that can have the disabled attribute applied (https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled#ov...)

Steps to reproduce

Create a form with a button element, and a #states rule which changes its disabled status. This problem can be seen with the submit button; example:

$form['actions']['submit'] = [ 
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#states' => [
    'disabled' => [':input[name="allow_overwrite"]' => ['checked' => FALSE]],
  ],  
];

Proposed resolution

Before change:

    if (e.trigger) {
      $(e.target)
        .closest('.js-form-item, .js-form-submit, .js-form-wrapper')
        .toggleClass('form-disabled', e.value)
        .find('select, input, textarea')
        .prop('disabled', e.value);
    }

Add additional HTML elements to the find() parameter: button, fieldset, optgroup, option.

After change:

    const tagsSupportDisable =
      'button, fieldset, optgroup, option, select, textarea, input';
    if (e.trigger) {
      $(e.target)
        .closest('.js-form-item, .js-form-submit, .js-form-wrapper')
        .toggleClass('form-disabled', e.value)
        .find(tagsSupportDisable)
        .addBack(tagsSupportDisable)
        .prop('disabled', e.value);
    }

Remaining tasks

User interface changes

None.

API changes

disabled property works again.

Data model changes

None.

Release notes snippet

Issue fork drupal-3354998

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

gapple created an issue. See original summary.

gapple’s picture

Status: Active » Needs review
Issue tags: +FAPI #states, +JavaScript, +Needs tests

Created a quick MR to update the element types that have disabled property set.

gapple’s picture

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

Definitely needs tests.

May even be worth a change record so others know they can disable those elements.

dww’s picture

For the tests this needs, see:

core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php
core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php

Feel free to ask me (here or Slack) if anyone needs help figuring out how to extend that test.

Thanks!
-Derek

jedihe made their first commit to this issue’s fork.

jedihe’s picture

StatusFileSize
new761 bytes

Uploading patch for the current MR.

The new patch fixes this use-case (which worked fine with Drupal 9.5.8):

$form['actions']['submit'] = [ 
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#states' => [
    'disabled' => [':input[name="allow_overwrite"]' => ['checked' => FALSE]],
  ],  
];
$form['actions']['allow_overwrite'] = [ 
  '#type' => 'checkbox',
  '#title' => $this->t('Allow overwrite'),
];

The idea is to use the checkbox as a simplistic "lock" that the user must "unlock" before being allowed to submit.

yevhenlebid51’s picture

Is there a solution for Drupal 9.5.8 version?

tallytarik’s picture

StatusFileSize
new803 bytes

Rerolled #8 for Drupal 9.5.8.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

daniel.pernold’s picture

Same problem here with Drupal 9.5.9. Patch #10 solved the problem.

jaypan’s picture

Title: #states cannot disable all element types » #states disable property has stopped working for some element types
Issue tags: -JavaScript +JavaScript
jaypan’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -JavaScript +JavaScript

Patch from #10 works for me

longwave’s picture

Status: Reviewed & tested by the community » Needs work

Needs reroll for 11.x first before we can consider backporting. Also as stated in #2 and #5 this could do with additional test coverage.

_utsavsharma’s picture

StatusFileSize
new749 bytes
new749 bytes

Reroll for 11.x as per #15.

a.dmitriiev’s picture

Worked for me on Drupal 9.5.10, thank you

devsoni’s picture

Thank you for the patch it seems working for drupal 10.1.x but as per project requirements I have added one more element "textfield" in patch file.

gapple’s picture

devsoni’s picture

StatusFileSize
new814 bytes
aadeshvermaster@gmail.com’s picture

hi @devsoni,

I applied your patch #20 in our project where drupal version is 9.5.10 and its working fine too.

Thanks

sonnykt’s picture

Patch #20 cannot be applied to Drupal 10.1.5.

Patch #16 can be applied and fixes the issue.

seth h’s picture

StatusFileSize
new1.22 KB

This patch is an updated version of #16 that also fixed an issue where e.value was undefined when the #states rules are no longer being met, and you are trying to set the 'enabled' state. This undefined-ness was leading to different behavior between toggleClass() and prop(), which was preventing the disabled prop not being set when it should have been, even though the form-disabled class was being set.

This very much feels like fixing the symptom and not the cause, but the cause is seemingly buried in the verifyConstraints/checkConstraints code which I unfortunately don't have time to dig into.

penyaskito’s picture

#23 didn't work for action submit element, but the MR did.

a.dmitriiev’s picture

#16 works for me, #23 doesn't work with checkboxes (at least)

phthlaap made their first commit to this issue’s fork.

phthlaap’s picture

Status: Needs work » Needs review
Issue tags: -JavaScript +JavaScript

I've created a merge request for version 11.x and added test coverage.

phthlaap changed the visibility of the branch 3354998-states-disable-elements to hidden.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: -JavaScript +JavaScript

Could it be documented what element types were discovered not working, IS mentions button but MR has other elements it's testing.

bobooon’s picture

StatusFileSize
new751 bytes

Adding D10.1 compatible patch based on latest MR.

phthlaap’s picture

Status: Needs work » Needs review

This issue happen with submit button

$form['actions']['submit'] = [ 
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#states' => [
    'disabled' => [':input[name="allow_overwrite"]' => ['checked' => FALSE]],
  ],  
];
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Issue summary and title should be updated to reflect that.

The issue summary and solution should line up.

Add additional HTML elements to the find() parameter.

What additional elements were added?

liam morland’s picture

Title: #states disable property has stopped working for some element types » #states disable property has stopped working for submit button and other elements
Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update

Updated issue summary. I am having this problem for submit buttons.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests, -Needs backport to 9.x +Needs issue summary update

Tests appear to be added so removing that tag

D9 is done so removing the backport tag.

Looking at the MR though it doesn't match what's proposed in the summary. Can the MR or summary be updated please

Left a small nitpicky but moving to NW for the summary.

liam morland’s picture

I have updated the merge request so that .find() includes all elements that support the disabled attribute. This means that the attributes added match what the summary says need to be added.

I note that the summary does not mention adding the call to .addBack(). Perhaps @phthlaap can add documentation about that.

phthlaap’s picture

Issue summary: View changes
Issue tags: -JavaScript +JavaScript
liam morland’s picture

Issue tags: -JavaScript +JavaScript

select, textarea, input are already in the .find(). That list is just the ones being added.

(I did not change the tagging; it is doing that itself.)

phthlaap’s picture

Issue summary: View changes
Issue tags: -JavaScript +JavaScript
phthlaap’s picture

Status: Needs work » Needs review
Issue tags: -JavaScript +JavaScript
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.41 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

smustgrave’s picture

How can the add back was needed?

liam morland’s picture

I looked in more detail at the history. .addBack() was in the patch in comment 8 by @jedihe and may be been there when the merge request was first opened in comment 3 by @gapple.

phthlaap’s picture

Status: Needs work » Needs review

Tested without addBack(tagsSupportDisable), the issue wasn't fixed. This change has been applied since patch #31.

gapple’s picture

I haven't checked the latest code in the merge request, but if IIRC, the addBack() was necessary because while in most cases the affected element has a wrapper with one of the relevant .js-form-item, .js-form-submit, .js-form-wrapper classes and the find() call will return the proper child node, there are some cases where the class is applied to the element itself.
While closest() will return the element it is called on if it matches the selector, find() does not. addBack() will append the element that was returned by closest() if it matches the list of element types.
Only one of find() or addBack() should return an element.

It should have the same result as this, without needing a variable or conditional block:

elem = eventTarget.closest(wrapperClasses);
if (!elem.is(tagsSupportDisable)) {
  elem = elem.find(tagsSupportDisable)
}
gapple’s picture

@jedihe was the one who added the addBack() in #7 / #8

https://git.drupalcode.org/project/drupal/-/merge_requests/3844/diffs?co...

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

Hiding patches for clarity

Ran test-only feature

1) Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest::testJavascriptStates
Failed asserting that false is true.
/builds/issue/drupal-3354998/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:121
/builds/issue/drupal-3354998/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
/builds/issue/drupal-3354998/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php:509
/builds/issue/drupal-3354998/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php:74
/builds/issue/drupal-3354998/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
FAILURES!
Tests: 1, Assertions: 213, Failures: 1.

Which shows test coverage

Issue summary appears to have been updated so removing that tag.

Thanks everyone for the digging into the addBack. Seems fine to me now

  • nod_ committed 3d3b2c1d on 11.x
    Issue #3354998 by phthlaap, Liam Morland, jedihe, gapple, smustgrave: #...

  • nod_ committed 46dd453d on 10.3.x
    Issue #3354998 by phthlaap, Liam Morland, jedihe, gapple, smustgrave: #...

  • nod_ committed abc51fb9 on 10.2.x
    Issue #3354998 by phthlaap, Liam Morland, jedihe, gapple, smustgrave: #...

nod_’s picture

Version: 11.x-dev » 10.2.x-dev
Status: Reviewed & tested by the community » Fixed

Committed 3d3b2c1 and pushed to 11.x. Thanks!

Status: Fixed » Closed (fixed)

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

Darren Oh made their first commit to this issue’s fork.