FAPI #states do not update properly after AJAX requests.

Steps to reproduce

To replicate the bug, you need a content type with a field that makes an AJAX request and another field that has a state dependent on that field. In my use case, I have a content type with an image field and a text field that should only show when an image has been uploaded.
1. Have a content type with an image and a text field
2. Create a custom module that adds a state to your text field to only display when the image field has value. It would look something like this:

use Drupal\Core\Form\FormStateInterface;

function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_page_form' || $form_id == 'node_page_edit_form') {
    $form['field_my_text_field']['#states'] = [
      'visible' => [
        ':input[name="files[field_my_image_field_0]"]' => ['filled' => TRUE],
      ],
    ];
  }
}

3. Go to your content type and upload an image. You would expect to see field_my_text_field because the image field has an image and the state should react to the AJAX call. However, you won't see field_my_text_field. Save your node, and go back to edit your node. Now you should see field_my_text_field.
4. Apply the patch from #80 and go through the steps again. Now on step 3, you should see field_my_text_field immediately after you upload an image.

Original report

I use a custom module which makes heavy use of the Forms API to do mathematical calculations.

The form which you can see at http://linsenrechner.de/node/27 is rendered with the #states attribute. each line uses a container to display two fields. When these fields are filled, a new line should appear.
This works perfect, BEFORE the calculation button is pressed and the ajax request is done.
After this, the behaviour of the form changes: When two fields of a specific line are filled not only one new line appears. In this case, all lines, which are defined in the form, appear at the same time.

The author of the custom module, sukr_s (http://drupal.org/user/554988) wasn't able to exactly locate the bug, but believes it's in states.js

Here are the form arrays, which are used to create the form at http://linsenrechner.de/node/27

$form['container0'] = array(
   '#type'   => 'container',
   '#weight'        => -53,
); 

$form['container0']['markup0'] = array(
   '#weight'        => -52,
   '#markup' => "<div id='ocalc_header_33'></div>
                 <div id='ocalc_header_33'>$ocalc_sag_height</div>
                 <div id='ocalc_header_33'>$ocalc_zone</div>",
); 


$form['container0'][$wrapper]['sag0'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_sag_height." 0",
    '#title_display' => 'invisible',
    '#weight'        => -51,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#prefix'  => "<div class='form-item-sag0'>$ocalc_zone 0</div>",
    '#field_suffix'  => "mm",
  );

$form['container0'][$wrapper]['zone0'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_zone." 0",
    '#title_display' => 'invisible',
    '#weight'        => -50,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm",
  );

$form['container1'] = array(
   '#type'   => 'container',
   '#weight'        => -43,
   '#states' => array('visible' => array(
		':input[name=sag0]'  => array ('filled' => TRUE),
		':input[name=zone0]' => array ('filled' => TRUE),
    ),
  ),
); 


$form['container1'][$wrapper]['sag1'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_sag_height." 1",
    '#title_display' => 'invisible',
    '#weight'        => -42,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm", 
    '#prefix' => "<div class='form-item-sag1'>$ocalc_zone 1</div>",
  );
  
 $form['container1'][$wrapper]['zone1'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_zone." 1",
    '#title_display' => 'invisible',
    '#weight'        => -41,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm",                   
  );
 
$form['container2'] = array(
   '#type'   => 'container',
   '#weight'        => -33,
   '#states' => array('visible' => array(
		':input[name=sag0]'  => array ('filled' => TRUE),
		':input[name=zone0]' => array ('filled' => TRUE),
		':input[name=sag1]'  => array ('filled' => TRUE),
		':input[name=zone1]' => array ('filled' => TRUE),
    ),
  ),
); 


$form['container2'][$wrapper]['sag2'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_sag_height." 2",
    '#title_display' => 'invisible',
    '#weight'        => -32,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm", 
    '#prefix' => "<div class='form-item-sag1'>$ocalc_zone 2</div>",
  );
  
 $form['container2'][$wrapper]['zone2'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_zone." 2",
    '#title_display' => 'invisible',
    '#weight'        => -31,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm",                 
  );

 
$form['container3'] = array(
   '#type'   => 'container',
   '#weight'        => -23,
   '#states' => array('visible' => array(
		':input[name=sag0]'  => array ('filled' => TRUE),
		':input[name=zone0]' => array ('filled' => TRUE),
		':input[name=sag1]'  => array ('filled' => TRUE),
		':input[name=zone1]' => array ('filled' => TRUE),
		':input[name=sag2]'  => array ('filled' => TRUE),
		':input[name=zone2]' => array ('filled' => TRUE),
    ),
  ),
); 


$form['container3'][$wrapper]['sag3'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_sag_height." 3",
    '#title_display' => 'invisible',
    '#weight'        => -22,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm", 
    '#prefix' => "<div class='form-item-sag1'>$ocalc_zone 3</div>",
  );
  
 $form['container3'][$wrapper]['zone3'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_zone." 3",
    '#title_display' => 'invisible',
    '#weight'        => -21,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm",                 
  );

$form['container4'] = array(
   '#type'   => 'container',
   '#weight'        => -13,
   '#states' => array('visible' => array(
		':input[name=sag0]'  => array ('filled' => TRUE),
		':input[name=zone0]' => array ('filled' => TRUE),
		':input[name=sag1]'  => array ('filled' => TRUE),
		':input[name=zone1]' => array ('filled' => TRUE),
		':input[name=sag2]'  => array ('filled' => TRUE),
		':input[name=zone2]' => array ('filled' => TRUE),
		':input[name=sag3]'  => array ('filled' => TRUE),
		':input[name=zone3]' => array ('filled' => TRUE),
    ),
  ),
); 


$form['container4'][$wrapper]['sag4'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_sag_height." 4",
    '#title_display' => 'invisible',
    '#weight'        => -12,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm", 
    '#prefix' => "<div class='form-item-sag1'>$ocalc_zone 4</div>",
  );
  
 $form['container4'][$wrapper]['zone4'] = array(
    '#type'          => 'textfield',
    '#title'         => $ocalc_zone." 4",
    '#title_display' => 'invisible',
    '#weight'        => -11,
    '#maxlength'     => 4,
    '#size'          => 4,
    '#field_suffix'  => "mm",                   
  );
CommentFileSizeAuthor
#186 1091852-186.patch10.67 KBdavid.muffley
#177 1091852-177.patch10.65 KBNicolas S.
#173 1091852-nr-bot.txt145 bytesneeds-review-queue-bot
#172 interdiff-171_172.txt697 bytesGauravvvv
#172 1091852-172.patch13.31 KBGauravvvv
#171 1091852-155-reroll-9.5.x.patch13.18 KBseanB
#170 1091852.patch13.95 KBedmund.dunn
#168 1091852-168.patch13.31 KB_utsavsharma
#168 interdiff_163-168.txt256 bytes_utsavsharma
#163 reroll_diff_155-163.diff3.65 KBmichaelsoetaert
#163 1091852-163.patch13.42 KBmichaelsoetaert
#155 interdiff-1091852-150-155.txt3.1 KByogeshmpawar
#155 1091852-155.patch13.18 KByogeshmpawar
#150 1091852-150.patch13.14 KBtbsiqueira
#149 1091852-57-147-interdiff.txt1.34 KBmibfire
#147 drupal-states_after_ajax-1091852-147.patch3.4 KBmibfire
#146 vbo-one-option-hidden.png273.63 KBmibfire
#146 vbo-one-option.png161.31 KBmibfire
#132 1091852-131-132-interdiff.txt4.48 KBroderik
#132 1091852-132.patch18.46 KBroderik
#132 1091852-132-test-only.patch12.09 KBroderik
#131 1091852-128-131.interdiff.txt6.72 KBroderik
#131 1091852-131.patch18.37 KBroderik
#131 1091852-131-test-only.patch12.09 KBroderik
#128 1091852-128.patch12.68 KBidebr
#128 1091852-128-test-only.patch7.1 KBidebr
#127 1091852-127.patch21.02 KBcarletex
#123 interdiff_122-123.txt1.58 KBraman.b
#123 1091852-123-d92.patch13.19 KBraman.b
#122 1091852-122-d92.patch13.14 KBdalin
#122 1091852-122-d91.patch13.52 KBdalin
#121 1091852-121-d92.patch13.14 KBdalin
#121 1091852-121-d91.patch19.32 KBdalin
#116 1091852-116.patch18.83 KBakasake
#115 1091852-115.patch35.22 KBseanB
#112 Screen Shot 2020-07-01 at 4.31.19 PM.png191.58 KBjoshua.boltz
#104 1091852-104-non-test-changes-do-not-test.patch6.39 KBDave Reid
#104 1091852-104.patch35.19 KBDave Reid
#104 1091852-interdiff.txt912 bytesDave Reid
#102 1091852-100.patch34.3 KBrensingh99
#102 interdiff.txt4.25 KBrensingh99
#100 1091852-100.patch34.23 KBrensingh99
#100 interdiff.txt4.03 KBrensingh99
#100 git_error.png6.91 KBrensingh99
#100 before_patch.png19.84 KBrensingh99
#100 after_patch.png13.58 KBrensingh99
#93 2702233-80.patch29.41 KBgease
#93 interdiff_80_93.txt5.61 KBgease
#93 1091852-93.patch11.68 KBgease
#93 1091852_with_2702233-full.patch34.91 KBgease
#80 1091852-80.patch5.5 KBTwoD
#79 Screen Shot 2018-11-07 at 5.13.26 PM.png81.59 KBAndySipple
#77 1091852-77.patch5.5 KBidebr
#70 interdiff-69-70.txt511 byteskfritsche
#70 1091852_70.patch5.42 KBkfritsche
#70 1091852_70-8.4.x.patch5.37 KBkfritsche
#68 interdiff-67-68.txt1.5 KBkfritsche
#68 1091852_68.patch5.42 KBkfritsche
#67 1091852_67.patch5.73 KBkfritsche
#60 drupal-states_after_ajax-1091852-60.patch3.2 KBkalistos
#57 drupal-states_after_ajax-1091852-57.patch3.54 KBron_s
#57 interdiff-1091852-39-57.txt1.12 KBron_s
#40 interdiff-1091852-33-39.txt999 bytesrooby
#40 drupal-states_after_ajax-1091852-39.patch3.15 KBrooby
#33 1091852-display-bug-when-using-states-with-ajax-request-33.patch3.09 KBjgullstr
#33 1091852-display-bug-when-using-states-with-ajax-request-33.patch3.09 KBjgullstr
#33 1091852-display-bug-when-using-states-with-ajax-request-33.patch3.09 KBjgullstr
#24 1091852-Display-Bug-when-using-states-with-Ajax-Request-24.patch1.92 KBhibersh
#18 states_bug.tar_.gz900 bytesandypost
#17 1091852-Display-Bug-when-using-states-with-Ajax-Request-16.patch1.77 KBsukr_s
#16 1091852-multiple-states.patch1.77 KBandypost
#13 1091852-Display-Bug-when-using-states-(Forms-API)-with-Ajax-Request-12.patch1.77 KBsukr_s
#11 1091852-Display-Bug-when-using-states-(Forms-API)-with-Ajax-Request-10-D7.patch1.77 KBsukr_s
#9 1091852-Display-Bug-when-using-states-(Forms-API)-with-Ajax-Request-8-D7.patch1.78 KBsukr_s
#6 1091852-Display-Bug-when-using-states-(Forms-API)-with-Ajax-Request-6-D7.patch2.16 KBsukr_s
#3 Fix for #states behaviour when using in combination with ajax-1091852-3.patch1.78 KBsukr_s
#1 1091852-Fix for #states behaviour when using in combination with ajax-1-D.patch1.78 KBsukr_s

Issue fork drupal-1091852

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sukr_s’s picture

Please review the patch to fix the above problem and needs to be integrated in to the main batch.

Status: Needs review » Needs work
sukr_s’s picture

Status: Needs work » Needs review
FileSize
1.78 KB

trying again with the patch instruction from http://drupal.org/node/3060/git-instructions/7.x

Status: Needs review » Needs work
sukr_s’s picture

Status: Needs work » Active

Can someone help on how to create a patch with git.
i followed the instruction from http://drupal.org/node/3060/git-instructions/7.x and named the patch as
[description]-[issue-number]-[comment-number].patch (comment 3). it does not work
and in comment 2 used
http://drupal.org/node/1054616 and named the patch [issue-number]-[description]-[comment-number]-D.patch
and this too did not work.
which of the two instructions are correct or did i miss something completely?

sukr_s’s picture

One more attempt...

danSamara’s picture

Status: Needs review » Reviewed & tested by the community

Same problem.
Thanks, patch work for me.

Anonymous’s picture

Status: Reviewed & tested by the community » Needs work

Nice work on getting the patch up. This didn't work for my issue, but I probably have a different issue in my module.

I'm marking it as needs work because there are some whitespace errors. I noticed this when I applied the patch because the command line returned this message: "3 lines add whitespace errors." If you use Dreditor, you'll be able to see the errors in pink.

sukr_s’s picture

Status: Needs work » Needs review
FileSize
1.78 KB

removed spaces

Anonymous’s picture

Status: Needs review » Needs work

Looks good except for one thing.

+++ b/misc/states.jsundefined
@@ -34,6 +30,33 @@ Drupal.behaviors.states = {
+ * Check needs to be performed if states object exists for a given
+ * selector and state combination. If this is not done, multiple states
+ * are created when used in combination with ajax. This results
+ * in wrong evaluation of states.   ¶

There is still a space at the end of this comment.

Powered by Dreditor.

sukr_s’s picture

Status: Needs work » Needs review
FileSize
1.77 KB

wondering how that escaped...

andypost’s picture

Version: 7.0 » 8.x-dev

Please make a patch against current 8-dev and use no D7 suffix to allow testbot run tests

EDIT Anybody can review this from performance side?

sukr_s’s picture

Status: Needs review » Needs work
sukr_s’s picture

i pulled

git clone --branch 8.x http://git.drupal.org/project/drupal.git 

and created the patch, but it has failed. I tried with 8-dev & 8.x-dev, but got a warning that both 8-dev and 8.x-dev does not exist. pls advise on the branch to use for creating patch.

andypost’s picture

Status: Needs work » Needs review
FileSize
1.77 KB

Testbot cant get your patch because of '(' in filename

so please reroll with a simple name like 1091852-multiple-states.patch

# wget http://drupal.org/files/issues/1091852-Display-Bug-when-using-states-(Forms-API)-with-Ajax-Request-10-D7.patch
bash: syntax error near unexpected token `('
sukr_s’s picture

@andypost: Thanks for your tip.

rerolling patch with clean name.

andypost’s picture

FileSize
900 bytes

Linked this issue with original issue to get 2 review #557272: FAPI: JavaScript States system

Also a lot of thanx to @dannie-walker module that demonstrates this bug

rfay’s picture

Subscribe. Some time ago I created a general #states testing regimen at https://github.com/rfay/states_exercise . Last I looked at it a few things didn't look like they worked right at all, but I didn't pursue it.

wjaspers’s picture

sub.

Berdir’s picture

Status: Needs review » Needs work

I have a similar issue, but I'm actually replacing a number of elements which have #states attached.

Basically, there is a select and for each value, there is a checkboxes element which shows up for a option of that select. Based on yet another radios element, I'm replacing all checkboxes elements with another set of them (different values/labels). The reason for that is that a combined #states definition does not seem to work reliably, after clicking around it falls apart and shows both options or something like that.

Without this patch, all checkboxes elements show up initially but after changing the select, it works correctly. With this patch, this stops working completely.

The inline comments in the patch also need work, they shouldn't be longer than 80 characters, be real sentences with a dot at the end, start with an uppercase character and a space before.. e.g. "// This is a correct inline comment."

akamaus’s picture

As Bendir I ran into the problems with the patch attached to #11. Without it after the first ajax call my js handler attached to document to 'state:required' event starts being called about a dozen of times on each value change of controlling select box. With this patch applied to D7.14 the state system seems to be totally disabled, no reactions on select box changes seem to occur.

akamaus’s picture

Component: forms system » search.module

I made some further experiments. Looks like the patch #11 works on D7.14 if corrected a bit.

+    new states.Dependent({
+      element: $(selector),
+      state: states.State.sanitize(state),
+      dependees: settings.states[selector][state]
+    });

here I had to replace 'dependees' with 'constraints'.

hibersh’s picture

Version: 8.x-dev » 7.x-dev
Component: search.module » forms system
Status: Needs work » Needs review
FileSize
1.92 KB

patch against drupal 7.x

Atomox’s picture

Any plans to roll this into a D7 release?

This also works for our issues.

Dmitriy.trt’s picture

Status: Needs review » Needs work

Last patch fails in our case. States event handler don't get re-binded to the AJAX-loaded elements, so it's impossible for other elements to depend on their state.

amar.deokar’s picture

Last patch also not worked for me. I am doing same as mentioned in comment #26.

alexweber’s picture

Weirdest thing, #24 worked in Chrome but not in Firefox, no errors to speak of though...

vyvee’s picture

Weird for me... #24 doesn't work for me at all, even in Chrome.

gagarine’s picture

Status: Needs work » Reviewed & tested by the community

I tested the patch #24 on Chrome 35 and Firefox 30. It works and I don't see how it could fail. Perhaps it was a browser cache problem?

gagarine’s picture

Status: Reviewed & tested by the community » Needs work

I see, if you replace the element with AJAX the states are not applied to this element again.

I think was what committed in D8 don't works neither but this should be tested.

Not sure how to fix that.. Any idea?

jgullstr’s picture

The states are not initialized on AJAX-requests, as the initialization is blocked by states.Trigger by the code

    if (!this.element.data('trigger:' + this.state)) {
      this.initialize();
    }

The reason to this guard is stated in the code to be

Only call the trigger initializer when it wasn't yet attached to this element. Otherwise we'd end up with duplicate events.

I'll have to examine further why this is necessary and how to solve the problem.

I'm not sure adding a states.CreateState function that checks for duplicates is the optimal solution. Wouldn't adding a behavior.detach method, that removes all traces of removed states, be a cleaner solution?

jgullstr’s picture

Here's a patch that tries to solve the lack of initial states application after AJAX requests. In order to make it work without messing up the API (ie custom state callback function implementation), I have repurposed the dependee elements "triggered" data attribute. Instead of containing a flag whether or not the trigger has been initialized, it now contains the current value of that state for that trigger, and loads initial value from that when behaviors are attached.

This patch does not attempt to solve the issue with cleaning up orphaned dependants.

jgullstr’s picture

Oops, looks like a went a little trigger happy on the upload button.

rooby’s picture

Thanks for the patch, this is a very frustrating bug for me at the moment.

I have a had a quick try and it seems to work in most cases but I've found a case where it is still a problem.

I have an addressfield where one of the fields in it is shown/hidden with states based on a set of radios outside the addressfield.

Whenever I select a country and the addressfield ajax runs, my states controlled field appears, regardless of which radio button is selected.

It is possible that this may be some other unrelated issue so I will investigate further.

rooby’s picture

Strange. I've done nothing since my last test but now it is working even for the addressfield case.

I will report back if it stops working again.

rooby’s picture

Not sure if it's just me but I'm having problems when I have ajax that loads new fields that weren't originally on the form or removes fields from the form that have states.

Initially I was getting these errors:

TypeError: this.element.data(...) is null

for line 319 of states.js:

if (!this.element.data().hasOwnProperty('trigger:' + this.state)) {

Just to see what would happen (since I don't yet have much knowledge of how it all works) I changed it to:

        if ($dependee.data() !== null && $dependee.data().hasOwnProperty('trigger:' + state.name)) {

and it fixed the error, after which states are working for fields that were always on the form but not for ones that were added via ajax.

(this is unrelated to my previous addressfield ramblings.)

rooby’s picture

Status: Needs review » Needs work

It turned out I had some other bugs that were causing states to not work on new form elements added by my ajax, however the "TypeError: this.element.data(...) is null" bug remains.

I now have this working successfully with my form, which is a pretty good use case of a large drupal commerce checkout form that has a complex set of visibility and required field states, a lot of form alters, custom ajax and custom javascript.

I will roll an updated patch with my fix for the is null bug.

rooby’s picture

Component: forms system » javascript
Status: Needs work » Needs review
FileSize
3.15 KB
999 bytes

Updated patch.

I assume this is also going to need new tests.

[edit] Damn, I forgot to re-check the comment number before I posted.

fbrier’s picture

I am having a problem with a Javascript multi-page FAPI form when wrapped in ctools so as to bring up a modal dialog. The page advance just hides fieldset(s) using the #states triggered by a hidden field. It works before bringing up the modal dialog, but after bringing up and dismissing the modal dialog, the HTML field the selector specifies changes, but the #states do not hide/show their fieldsets(s). trigger() is explicitly being called on the tag using the selector, plus it works before the modal is opened/closed.

Initially my problem sounded like this bug #1592688: #states can cause the form "required" mark to appear more than once on the same element. Feeling in luck since the new 7.40 release was rolled out yesterday, I upgraded. Unfortunately, it did not fix it. So I cloned the git repo, branched 7.40, applied the above drupal-states_after_ajax-1091852-39.patch, and copied states.js up to the server. No change in behavior. Now David_Rothstein patch was also to the states.js file, but obviously to 7.39. Would this make a difference? The patch appeared to apply cleanly. Thank you.

hestenet’s picture

moonray’s picture

A similar (or the same) problem seems to be happening with D8 as well. I'll test the patch (and adapt it where need it) on D8 and report back.

moonray’s picture

This is definitely an issue in D8.
The D7 fix (manually applied) doesn't work for me in D8 and would need to be tweaked/fixed.

moonray’s picture

(removed duplicate post)

Anonymous’s picture

The patch in #40 is working for me.

Anonymous’s picture

Status: Needs review » Reviewed & tested by the community
stefan.r’s picture

Ideally this should be fixed in D8 first (where I believe we can also now add tests for this).

sumthief’s picture

Confirm that patch from #40 works perfect for 7.50 on my current project.

stefan.r’s picture

Version: 7.x-dev » 8.1.x-dev
Assigned: Unassigned » nod_
Status: Reviewed & tested by the community » Active

This also applies to Drupal 8 per #44, so assigning this to 8.x per the backport policy.

Possibly we already have an existing issue for this?

stefan.r’s picture

Assigned: nod_ » Unassigned
David_Rothstein’s picture

Issue tags: +Needs backport to D7
nbouhid’s picture

I created a module that provides a temporary fix for those that does not want to patch the core and wait until this fix gets merged: https://www.drupal.org/sandbox/nbouhid/2776183 (D7)

We're using it and it works fine.

odegard’s picture

Thanks nbouhid! Working as advertised. I've got a doublefield showing both fields if different field A is X and only one field if A is Y. The old states.js showed both fields even when A is Y after adding another item. The new states.js fixes this.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ron_s’s picture

For anyone using patch #40 or the sandbox project created by @nbouhid for Drupal 7, there are two critical errors. CKEditor fails to load every time in a ctools popup window (such as for Panels) due to these lines of code:

if ($dependee.data() !== null && $dependee.data().hasOwnProperty('trigger:' + state.name)) {
if (this.element.data() !== null && !this.element.data().hasOwnProperty('trigger:' + this.state)) {

The error generated by the console is as follows, pointed at $dependee.data() and !this.element.data(), respectively:

Uncaught TypeError: Cannot read property 'hasOwnProperty' of undefined

It does not matter if using the CKEditor or WYSIWYG modules, it fails in both cases. Rolling back the patch fixes the problem.

ron_s’s picture

Attached is an updated patch for review that checks if the objects are defined. Thanks.

Tim Bozeman’s picture

Status: Active » Needs review

#57 is a good addition!

I was getting the AJAX + states display bug and #40 fixed it, but I was getting Uncaught TypeError: Cannot read property 'hasOwnProperty' of undefined which was fixed by #57.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kalistos’s picture

Thanks #57 helped me, but it's on Drupal 8.2, so I have updated it for Drupal 8.3.

ron_s’s picture

@kalistos, patch #57 is not Drupal 8.2. It is for Drupal 7.

droplet’s picture

idebr’s picture

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jwilson3’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

Patch in #60 doesn't apply to 8.4.x since the move to es6 for all javascript.

Ivan Berezhnov’s picture

Issue tags: +CSKyiv18
kfritsche’s picture

Version: 8.4.x-dev » 8.5.x-dev
Issue tags: -Needs reroll
FileSize
5.73 KB

First a re-roll. Not setting to needs review as I'm currently also doing some small changes, but for this an interdiff would be good.

kfritsche’s picture

Status: Needs work » Needs review
FileSize
5.42 KB
1.5 KB
  1. +++ b/core/misc/states.es6.js
    @@ -146,10 +148,16 @@
    +          $dependee.bind(`state:${state}`, { selector, state }, stateEventHandler);
    

    Why change from on to bind?
    Unnecessary change in my mind.

  2. +++ b/core/misc/states.es6.js
    @@ -146,10 +148,16 @@
    +          if (typeof $dependee.data() !== 'undefined' && $dependee.data() !== null && $dependee.data().hasOwnProperty('trigger:' + state.name)) {
    
    @@ -368,7 +376,7 @@
    +      if (typeof this.element.data() !== 'undefined' && this.element.data() !== null && !this.element.data().hasOwnProperty('trigger:' + this.state)) {
    

    Don't like this, to much clutter :/

    This is also not needed in my mind. As we just can check for undefined. jquery data does the rest.

Changes applied.

Status: Needs review » Needs work

The last submitted patch, 68: 1091852_68.patch, failed testing. View results

kfritsche’s picture

Status: Needs work » Needs review
FileSize
5.37 KB
5.42 KB
511 bytes

Small issue on the second change from #68. For second occurrence it needs to be checked for equals undefined.

Also adding patch for 8.4.x if anybody else needs it (we do)

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mohit_aghera’s picture

Status: Needs review » Reviewed & tested by the community

Tested this with 8.4.x and seems working fine.
Tested with nested paragraph and related #states logic, works fine with paragraphs as well.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

We need a JavascriptTestBase test for this. We can now test javascript interaction in D8 so a failing test without the fix and a passing test with the fix would great.

nwoodland’s picture

Patch from #70 works great on 8.5. Thanks!!

idebr’s picture

Issue tags: +Needs reroll

The patch in #70 needs a reroll after #2917234: [2/2] JS codestyle: no-restricted-syntax was committed.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

idebr’s picture

nikathone’s picture

Just to mention that the patch #40 fixed my issue on a d7.60.

AndySipple’s picture

Updated core from 8.5 to 8.6.3. Patch #70 applied cleanly on 8.5 but does not apply cleanly on 8.6.3.

TwoD’s picture

FileSize
5.5 KB

Re-rolled again because the compiled version no longer applied.

Status: Needs review » Needs work

The last submitted patch, 80: 1091852-80.patch, failed testing. View results

tstoeckler’s picture

Status: Needs work » Needs review

HEAD was broken...

Nuuou’s picture

Posting this here as it's relevant to an issue I ran into recently.

These patches work great. However, it also seems to conflict in an odd way with the Webform module. Nothing that's terribly bad, but definitely noticeable. Related issue thread:
https://www.drupal.org/project/webform/issues/2996530

Again, not sure if this is actionable, but might be of interest if anyone else notices this!

idebr’s picture

The issue reported in #83 in the Webform module has been resolved, see #2996530: AJAX Settings visibility state based on non-existing DOM element

The webform module evaluated the visibility of a container on the value of a non-existing DOM element. Currently, this is evaluated as 'visible' but after applying the updated States logic implemented here this evaluates as 'invisible'. It was solved by removing the visibility states implementation.

mukun’s picture

Updated core from 8.3.9 to 8.6.7. Patch #60 works on 8.3.9 but does not applied on 8.6.7.
message was could not apply patch while update core.

Nuuou’s picture

@mukun: I'm currently applying patch #80 with Drupal 8.6.7, and it's applying cleanly. Might wanna try that out!

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nwoodland’s picture

Patch from #80 on Drupal 8.6.13 and PHP 7.2.15 works great. Thanks!

carletex’s picture

I had the same issue (#states not working after an AJAX call) and patch #80 fixed the issue.

Tested on Drupal 8.6.13.

jonathanshaw’s picture

In order to make a test, it would help to have clear steps to reproduce.

angelamnr’s picture

@jonathanshaw: To replicate the bug, you need a content type with a field that makes an AJAX request and another field that has a state dependent on that field. In my use case, I have a content type with an image field and a text field that should only show when an image has been uploaded.
1. Have a content type with an image and a text field
2. Create a custom module that adds a state to your text field to only display when the image field has value. It would look something like this:

use Drupal\Core\Form\FormStateInterface;

function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_page_form' || $form_id == 'node_page_edit_form') {
    $form['field_my_text_field']['#states'] = [
      'visible' => [
        ':input[name="files[field_my_image_field_0]"]' => ['filled' => TRUE],
      ],
    ];
  }
}

3. Go to your content type and upload an image. You would expect to see field_my_text_field because the image field has an image and the state should react to the AJAX call. However, you won't see field_my_text_field. Save your node, and go back to edit your node. Now you should see field_my_text_field.
4. Apply the patch from #80 and go through the steps again. Now on step 3, you should see field_my_text_field immediately after you upload an image.

gease’s picture

gease’s picture

gease’s picture

The patches add a test to the patch from #80. As Form State API tests are being developed in #2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked, I extended the patch from #2702233-76: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked with a test based on module from #18.
Uploaded patches contain:
1091852_with_2702233-full.patch - patches from current issue #80, #2702233-76: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked, and the test for current issue. It should pass tests.
2702233-80.patch - tests from #2702233-76: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked extended with the test for the current issue, but without the patch for the current issue. This should fail through testing.
1091852-93.patch - patch from #80 and test for it, applied over #2702233-76: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked. This should even fail applying to 8.8.x until the latter patch is committed.

Status: Needs review » Needs work

The last submitted patch, 93: 2702233-80.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jonathanshaw’s picture

It would help to get a JS maintainer to look at this now.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

adam-delaney’s picture

Issue tags: -JavaScript +JavaScript

I've tested https://www.drupal.org/files/issues/2019-09-12/1091852_with_2702233-full... and it applies cleanly and resolves my issue.

https://www.drupal.org/files/issues/2019-09-12/1091852-93.patch against 8.7.10 does not apply.

Thanks for the work on this issue.

adam-delaney’s picture

UPDATE https://www.drupal.org/files/issues/2019-09-12/1091852_with_2702233-full..., introduces a regression where the revision log field is hidden when new nodes are created. Is this intended behavior?

rensingh99’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
13.58 KB
19.84 KB
6.91 KB
4.03 KB
34.23 KB

Hi,

I have applied the patch #93 with 8.9x and it failed to apply.

I have made it compatible with 8.9x.
And there was some error as per Drupal coding standard I have solved that too and uploaded the patch with interdiff.

After that, I have tested the patch and it worked as design.

Below are my updates.

1). I have added the text field in the article content type.

2). I have made it dependent on the image field using hook_form_alter().

Before applying the patch
The text field didn't show after uploading the image. Below is the output screenshot.

After applying the patch
The text field did show after uploading the image. Below is the output screenshot.

The patch is working great.

Thanks,
Ren

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 100: 1091852-100.patch, failed testing. View results

rensingh99’s picture

rensingh99’s picture

Status: Needs work » Reviewed & tested by the community
Dave Reid’s picture

We've identified that this actually causes a regression with the "Revision log message" field on new nodes. Because it has a state that is dependent on the revision checkbox being checked, and on new forms this checkbox is not in the form at all, the revision log field is hidden when it should not be. I've included a change that fixes this to add the state conditionally in ContentEntityForm. But this will need test coverage to ensure it does not break. As such I'm marking this as Needs work for now.

mdolnik’s picture

Patch #104 is working for us in 8.8.x

bgreco’s picture

Patch #104 solves a slightly different issue for me on 8.8.x.

I have an entity form that includes a Media Library widget. It includes a second field whose #states depend on the value of a third field. If I load the form and click "Add media", the #states on the second field no longer work, despite the Media field not being involved in the #states at all. I think the patch fixes my issue because of its care to not to call the state changes multiple times.

nodecode’s picture

I'm coming from #3114741: [#States API] AJAX and Conditionals Conflicting and can confirm that patch #104 resolves this and multiple related issues with the Webform module, states, and AJAX. I'm currently on Drupal 8.8.2.

Andras_Szilagyi’s picture

Status: Needs work » Reviewed & tested by the community

Tested #104, works great, I also added the 7.2 and 7.3 env tests, green.
Patch has great tests and interdiff, what are we waiting for ?

jonathanshaw’s picture

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

Per #104 this needs a little more test coverage, so cannot be RTBC

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

joshua.boltz’s picture

I'm seeing similar issues to this when using #states for conditional field logic on node forms, although instead of the ajax coming from a custom form like in this issue, the ajax would be from paragraphs with its edit links.

On typical node add and node edit forms, it's working great.

But, in my site, I have a case where via paragraphs, there is an entity reference field using entity browser, that allows users to edit the referenced entities within the entity browser, and when clicking the Edit link the first time, the #states work. But if i close that window and try to Edit another reference node in there, the #states does not work.

Here is my #states code

if ($form_id == 'node_detail_page_form' || $form_id == 'node_detail_page_edit_form') {
    $form['field_alternate_title_url']['#states'] = [
      'invisible' => [
        ':input[name="exclude_node_title"]' => ['checked' => TRUE],
      ],
    ];
}

I also tried this patch and it did not solve the issue.

See screenshot - https://www.drupal.org/files/issues/2020-07-01/Screen%20Shot%202020-07-0...

joshua.boltz’s picture

joshua.boltz’s picture

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

seanB’s picture

Reroll for 9.1.x

Darren Oh’s picture

Status: Needs work » Needs review
jannakha’s picture

Status: Needs review » Needs work

102 worked for 8.9! Hurray!

jannakha’s picture

Status: Needs work » Needs review
beckydev’s picture

#104 resolved our issue on 8.9.13.

dalin’s picture

Here's a reroll, both for 9.1, and HEAD of 9.2.

Someone definitely needs to check these tests. I know a little about PHP tests, and nothing about JS tests. I hope I didn't mangle them.

dalin’s picture

The drop is always moving. Here's another reroll to catch up to HEAD, and to fix the linting issues.

But again, someone who understands JS tests needs to review the tests.

raman.b’s picture

Lendude’s picture

Status: Needs review » Needs work

When you reroll, please check that the patch size stays roughly the same. We lost about half the patch (all the new test coverage) between #115 and #116. So please reroll but base this on a version that still contains everything please.

idebr’s picture

Issue tags: +Needs reroll
dalin’s picture

I think the confusion in the tests is because much of it was committed in at least three other issues:
https://git.drupalcode.org/project/drupal/-/blame/9.2.x/core/tests/Drupa...
https://git.drupalcode.org/project/drupal/-/blame/9.2.x/core/modules/sys...

But we did seem to loose

  • \Drupal\FunctionalJavascriptTests\Core\Form->testAjaxJavascriptStates()
  • All the additions to core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php
  • All the additions to core/modules/system/tests/modules/ajax_forms_test

We'll need to get those back before this is commitable.

carletex’s picture

Following @Lendude and @dalin comments, this is my attemp to reroll the patch from #115 (so we don't loose what @dalin mentioned) to catch up with 9.2.x.

idebr’s picture

The JSWebAssert changes were removed on purpose in #2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked, see comments #105 -> #109

Attached updated the assertions in \Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest::testAjaxJavascriptStates() method to match the other assertions in the file.

The last submitted patch, 128: 1091852-128-test-only.patch, failed testing. View results

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

roderik’s picture

This patch solves a related but different issue for me: if fields are dynamically added to the form by an AJAX call, which have #states (depending on a form item that was present already)... those #states are not applied.

Before I started messing with the JS, I added tests for that situation.

Disclaimer: I cannot properly review this because I'm not a JS developer; I only get half of the code.

But I noticed that

+++ b/core/misc/states.js
@@ -240,15 +246,9 @@
-      states.postponed.push($.proxy(function () {
-        this.element.trigger({
-          type: "state:".concat(this.state),
-          value: oldValue,
-          oldValue: null
-        });
-      }, this));

...removes the only code that changes states.postponed. So if this is the right way of doing things, we should remove any reference to states.postponed.

Tried that; the tests still succeed.

My biggest question now is: are we even allowed to essentially replace this whole states.postponed.push() mechanism with the single call to this.reevaluate() in states.Dependent?

I'm thinking it wasn't there for nothing. It feels like

  • either it prevented reevaluate() from being called on the dependent objects too many times,
  • or it prevented calling reevaluate() when 'things' may not be fully initialized yet.

I'm guessing it's the second. I'm guessing this 'postponed' mechanism had a good reason for being there. But this JS makes my head spin so I can't answer that.

(I tried reverting the removal of the above code + addition of the this.reevaluate() call, but that made things fail again.)

roderik’s picture

The last submitted patch, 132: 1091852-132-test-only.patch, failed testing. View results

roderik’s picture

So summarizing, AFAICT this needs

  • Per #104: test coverage to make sure that the ContentEntityForm.php change doesn't break in the future? (I guess this means, show an entity revision form when $form['revision']['#access'] == FALSE, and ensure the log message element is visible - which would currently break in HEAD? Possibly to be broken out into a separate issue if someone thinks that speeds things up...)
  • A good review including an opinion/answer on the question in #131.
jonathanshaw’s picture

It sounds like #104 could be triggered by a form alter anyway, even without this issue. In which case, yes it's a good candidate for handling as a separate issue. I'm happy to do reviews on that issue if you'll code it.

jonathanshaw’s picture

Given this is an old, major bug that's proven difficult to fix, I think it's reasonable to ask for a js maintainer's review. Which may answer #131.

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

owenbush’s picture

I've cleaned up patch #132 (there was a .rej file presumably from a previously failed patch which I have removed) and put it into a merge request so that any changes can be more easily added.

I attempted to add the tests mentioned in #104 and #134 and am wondering whether it would be better to break those out elsewhere. Ideally we need a test entity with revisions enabled in order to test the revision log message field does not disappear after an AJAX request. Core does have the entity_test_revlog entity with revision logging enabled, but there are no forms and routes configured that are accessible to the javascript functional tests. So should testing that functionality live with the entity_test tests, or still within the Javascript state tests. I'm happy to try again with the tests, but not sure as to the desired approach. Thoughts welcome.

jonathanshaw’s picture

I attempted to add the tests mentioned in #104 and #134 and am wondering whether it would be better to break those out elsewhere.

I think so

Core does have the entity_test_revlog entity with revision logging enabled, but there are no forms and routes configured that
are accessible to the javascript functional tests.

Sounds like we'll need to add them.

So should testing that functionality live with the entity_test tests, or still within the Javascript state tests.

Seems like this is really an issue with the revision logging, not generically with the javascript states. So entity_test... I'd say.

roderik’s picture

Yes, it feels like testing that part is best off connected to 'whatever else Core has in that area' (entities, revisions, I'm not aware of the setup of those tests personally). And doesn't need to be tied in with the JS + its tests at all.

yoshiet p’s picture

Patch #104 seems to be working fine in my use case where #states would not initialize after ajax request.

mibfire’s picture

https://www.drupal.org/project/drupal/issues/1091852#comment-11611711

I have an issue with Views Bulk Operations (VBO) module when there is only one option that you can modify in bulk, for example when you want to modify values of a reference field of nodes.

VBO with one option

In this case this one option will be hidden

VBO with one option is hidden

, because the "show value" checkbox is changed to "#type = 'value'"

https://git.drupalcode.org/project/views_bulk_operations/-/blob/7.x-3.x/...

  // If the form has only one group (for example, "Properties"), remove the
  // title and the fieldset, since there's no need to visually group values.
  $form_elements = element_get_visible_children($form);
  if (count($form_elements) == 1) {
    $element_key = reset($form_elements);
    unset($form[$element_key]['#type']);
    unset($form[$element_key]['#title']);

    // Get a list of all elements in the group, and filter out the non-values.
    $values = element_get_visible_children($form[$element_key]);
    foreach ($values as $index => $key) {
      if ($key == 'show_value' || substr($key, 0, 1) == '_') {
        unset($values[$index]);
      }
    }
    // If the group has only one value, no need to hide it through #states.
    if (count($values) == 1) {
      $value_key = reset($values);
      $form[$element_key]['show_value'][$value_key]['#type'] = 'value';
      $form[$element_key]['show_value'][$value_key]['#value'] = TRUE;
    }
  }

and when "this.reevaluate();" runs in "states.Dependent = function (args) {" then it hides it because i think the dependency is not in the html.

misc/states.js:48

states.Dependent = function (args) {
  $.extend(this, { values: {}, oldValue: null }, args);

  this.dependees = this.getDependees();
  for (var selector in this.dependees) {
    this.initializeDependee(selector, this.dependees[selector]);
  }
  // Reevaluate to execute initial states.
  this.reevaluate();
};

I have a proposal for the fix, but i am not sure this is the right one and covers all cases. I think we should check if at least one selector exists in the html and if yes we call the "this.reevaluate()" function only in this case.

states.Dependent = function (args) {
  $.extend(this, { values: {}, oldValue: null }, args);

  this.dependees = this.getDependees();
  for (var selector in this.dependees) {
    this.initializeDependee(selector, this.dependees[selector]);
  }
  // Reevaluate to execute initial states.
  // Check if there is at least one selector in the html.
  for (selector in this.dependees) {
    if ($(selector).length) {
      this.reevaluate();
      break;
    }
  }
};

As i see this affects Drupal 8 & 9 too.

mibfire’s picture

FileSize
161.31 KB
273.63 KB
jonathanshaw’s picture

I made a patch based on https://www.drupal.org/files/issues/drupal-states_after_ajax-1091852-57....

Was there a reason you didn't use the latest version as discussed in #141?

Additionally, it helps enormously if you can provide an interdiff.

mibfire’s picture

@jonathanshaw

Was there a reason you didn't use the latest version as discussed in #141?

Why would i have used that patch? when i fixed the d7 version not the Drupal 8&9 version. I made the diff though.

tbsiqueira’s picture

I'm re-rolling the patch to be able to apply to a 9.1.x core version, I also removed a couple of duplicated files and tests, for now I just need to apply the code change.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

VladimirAus’s picture

Status: Needs review » Reviewed & tested by the community

Work fine.

catch’s picture

Status: Reviewed & tested by the community » Needs work

JavaScript linting is failing.

superlolo95’s picture

+1 for #150

yogeshmpawar’s picture

Status: Needs work » Needs review
FileSize
13.18 KB
3.1 KB

Fixed CS issues.

bryantgeorge’s picture

Status: Needs review » Reviewed & tested by the community

#155 seems to fix the issue for me

jonathanshaw’s picture

Status: Reviewed & tested by the community » Needs work

NW for #142 test tidy up.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

akalam’s picture

#155 is working for me

szato’s picture

#155 and MR749.diff works for me, but there is an another (maybe separate?) issue:
I'm using paragraphs on modal and using same machine name for fields with states on parent node and in paragraphs too. Because of the same field machine name, states on modal doesn't work only on the parent node form. If I use separate field machine names, the states works in parent node form and in paragraphs modal form too.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

sker101’s picture

I'm having a similar issue with an ajax callback applied element on one of our webforms and confirmed that the patch #155 fixes my issue.

However, I'm seeing some regressions on the form after applying the patch due to using multi wizard page on the form.

We have a select element on wizard page 2 and its visible condition is depending on another element which only exists on the wizard page 1.

After applying the patch, the select element on wizard page 2 is no longer visible regardless what value we have on the element of wizard page 1.

Our solution for now is to create a form alter to make the element on wizard page 1 visually hidden on wizard page 2 so that the value could be
respected by the select element on wizard page 2.

Due to this issue, we have to thoroughly review all other webforms we have on the site that use multi wizard page.

michaelsoetaert’s picture

I've re-rolled the patch in #155 on the 9.5x branch.

_utsavsharma’s picture

Status: Needs work » Needs review
adam-delaney’s picture

I'm not able to apply patch #163 with Drupal 9.5 with error, `patch fails to apply`.

adam-delaney’s picture

Status: Needs review » Needs work
adam-delaney’s picture

Status: Needs work » Needs review

Sorry, I've made a mistake checking our build output. Putting back into needs review

_utsavsharma’s picture

Status: Needs review » Needs work

The last submitted patch, 168: 1091852-168.patch, failed testing. View results

edmund.dunn’s picture

seanB’s picture

Another attempt to reroll #155.

Gauravvvv’s picture

Fixed CCF, attached interdiff for same. Please review

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
145 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

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

DrColossos’s picture

#172 applies and works in 9.5.3

yovanny.gomez.oyola’s picture

#172 applies and works in 9.5.5. Thanks!

Nicolas S.’s picture

Patch #172 works for me with a Drupal 9.5.9

Nicolas S.’s picture

Status: Needs work » Needs review
FileSize
10.65 KB

Fix patch for Drupal 10.1.x

Status: Needs review » Needs work

The last submitted patch, 177: 1091852-177.patch, failed testing. View results

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.

SajithAthukorala’s picture

Having Issues with #132 on Drupal Version 9.5.9 132: 1091852-132.patch , It gives an errors on page load where we use #states attributes in fields. This may cause the page load js errors and not recommend to use it . Thank You !!!

adam-delaney’s picture

I've tested Drupal 10.1 with a clean install using the steps in the description to reproduce the issue and I'm not able to reproduce it. This seems to have been fixed in states.js for Drupal 10.

maithili11’s picture

Patch #172 works for me with a Drupal 9.5.8

Dave Reid’s picture

I can no longer replicate this issue on Drupal 9.5 or 10 and I think the fix in #1988968: Drupal.ajax does not guarantee that "add new JS file to page" commands have finished before calling said JS core issue, but I haven't been able to confirm that. I think we need someone to provide a reproducible scenario (I used the one in the issue description, and I could no longer reproduce it) or possibly close this as fixed. I do wish I knew exactly what core issue seems to have resolved it, I don't feel easy closing this until we know.

david.muffley’s picture

I'm still having this issue on a form submit button whose state depends on some facets elements. #177 resolves the issue for me. I'll try to produce a trimmed down reproducible scenario like the one I'm experiencing soon™.

Robin.Houtevelts’s picture

I can also confirm I'm still having this problem on 10.1.
Applying #177 resolved it for me.

david.muffley’s picture

Rerolled #177 for 10.2.

keshavv’s picture

Confirm I'm still having this problem on 10.2.
Applying #186 resolved it for me.

jonathanshaw’s picture

@robin.houtevelts @keshavv steps to reproduce - or at least come comments on the circumstances in which you're encountering this bug - would be really helpful.

chrisgross’s picture

I'm still having what I think is the same issue and the latest patch does not fix it. Perhaps this is a slightly complicated example, but I will simplify it as best as possible.

Here I have I two select lists. The first one uses an ajax callback to modify the options contained within the second one, which has a couple hardcoded default values:

$form['billing_date'] = [
  '#type' => 'select',
  '#title' => t('Billing Month'),
  '#options' => $options,
  'callback' => '::equipmentUpdate',
];

$form['equipment'] = [
  '#type' => 'container',
];

$form['equipment']['equipment_id'] = [
  '#type' => 'select',
  '#title' => t('Equipment Number'),
  '#options' => [
    0 => '- Select - ',
    'other' => 'Enter manually'
  ],
];

My custom equipmentUpdate callback does a lot of other things, but here is the command I use to update the options of the second select list:

$response->addCommand(new ReplaceCommand('#edit-equipment .form-item-equipment-id', $equipment)

This ReplaceCommand occurs after $equipment (which is a copy of $form['equipment']['equipment_id']) has been modified to add new values after the two defaults set earlier.

That functionality works just fine, but what does not is the state of a third field, whose visibility depends on a value contained within the second select list, which is modified by the ajax call:

$form['equipment']['equipment_id_other'] = [
  '#type' => 'textfield',
  '#title' => t('Equipment Number'),
  '#states' => [
    'visible' => [
      ':input[name="equipment_id"]' => [
        'value' => 'other'
      ],
    ],
  ],
];

Before the ajax callback, the visibility of this text field is correctly controlled by the equipment_id select list. After the callback completes, this no longer works, and the visibility of this field does not change. I have tested by experimenting with other ways of organizing the data and using different ajax commands, like HtmlCommand, but nothing works. No matter what I do, subsequent ajax calls continue to correctly modify the select list values, but the visibility state of the text field is broken.

I have confirmed that all the markup in all fields and wrappers are exactly the same before and after the ajax command, except that that ajax operations change element ids, for example, from edit-equipment-id to edit-equipment-id--Ronn-Os05Q0. But my visibility selector is targeting the name attribute, which does not change, so this shouldn't matter.

I have been able to work around this by not using ReplaceCommand to replace the entire select element and instead manipulate the option elements directly:

foreach ($results as $result) {
  $id = $result['id'];
  $response->addCommand(new RemoveCommand('#edit-equipment select option[value="other"] ~ option'));
  $response->addCommand(new AfterCommand('#edit-equipment select option[value="other"]', '<option value="' . $id . '">' . $id . '</option>'));
}

This works, but should not be necessary, as replacing the entire select list should not cause the states of another field to stop working. Doing it this way is also mildly inconvenient because, as far as I can tell, I cannot pass options as a render array (or a subset thereof) to the ajax commands, so I have to write the markup for each option manually.

It seems that simply replacing a form element that is the dependency of another element, even with an identical copy of itself, breaks states for the dependent element, whereas modifying the contents does not.