Problem/Motivation
With #3294720: The attachBehaviors() for document is only called after Big Pipe chunks are processed the Drupal Behaviors are being applied for entire page twice.
This causes, that states' rules are initiated multiple times and this causes that states sometimes works unexpected if BigPipe is available.
Steps to reproduce
Create a form containing complex states logic:
$form['option'] = [
'#type' => 'radios',
'#title' => 'Option',
'#options' => [
'option_1' => 'option_1',
'option_2' => 'option_2',
],
'#default_value' => 'option_1',
'#required' => TRUE,
];
$form['variant'] = [
'#tree' => TRUE,
];
$form['variant']['option_1'] = [
'#type' => 'radios',
'#title' => 'Variant for option_1',
'#options' => [
'variant_1' => 'variant_1',
'variant_2' => 'variant_2',
],
'#default_value' => 'variant_1',
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name="option"]' => ['value' => 'option_1'],
],
],
];
$form['variant']['option_2'] = [
'#type' => 'radios',
'#title' => 'Variant for option_2',
'#options' => [
'variant_1' => 'variant_1',
'variant_2' => 'variant_2',
],
'#default_value' => 'variant_1',
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name="option"]' => ['value' => 'option_2'],
],
],
];
foreach($form['option']['#options'] as $option_key => $option_title) {
foreach($form['variant'][$option_key]['#options'] as $variant_key => $variant_title) {
$key = $option_key . '__' . $variant_key;
$form['info'][$key] = [
'#type' => 'container',
'#states' => [
'visible' => [
':input[name="option"]' => ['value' => $option_key],
':input[name="variant[' . $option_key . ']"]' => ['value' => $variant_key],
],
],
'text' => [
'#markup' => 'info for option ' . $option_title . ' variant ' . $variant_title,
],
];
}
}
And for visitor with BigPipe enabled (f.e logged in) the first click on any radio button will lead that text line will not be visible at all.
Other clicks on any radio will work as expected.
Proposed resolution
Use `once` to select element with defined states to apply them.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3347144
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
Comment #2
evaldas.uzkurasComment #3
evaldas.uzkurasHere's a patch adding use of `once` as I proposed.
Comment #4
rodrigoaguileraThank you for creating the issue and providing a patch.
Bugs should be fixed in the latest dev version of Drupal and then backported to older versions like 9.5.x when applicable.
Since D10 doesn't use es6.js files anymore the patch needs to be different for D10.
Also we should provide one of this scenarios as a js test to be able ensure the behaviour stays consistent in the future
Comment #6
dgtlmoon commentedI can confirm this issue atleast in 9.5 and 9.2, the patch at #3 resolves it for me, atleast in my situation BigPipe is not used when anonymous/not-logged-in, but on logged in, bigpipe is activated and then I get missing form states, btw @evaldas-užkuras thanks!!
Comment #7
dgtlmoon commentedComment #9
dgtlmoon commentedThere is this one which is sort of related https://www.drupal.org/project/drupal/issues/3337995 but was closed
Comment #10
abrammI'm a bit surprised that
#stateswasn't usingonce(), it's even declared as dependency to thedrupal.stateslibrary.This is definitely a bug which affects BigPipe and AJAX use cases. The patch looks correct (didn't test it though).
Comment #11
dgtlmoon commentedComment #12
dgtlmoon commentedJust throwing this out there, maybe `states` doesnt bind with the right 'context' ? https://www.drupal.org/project/drupal/issues/3337995#comment-15060748
Comment #13
dgtlmoon commentedComment #14
dgtlmoon commentedComment #15
smustgrave commentedDid not test.
But was previously tagged for tests which still need to happen. May be worth posting in #testing channel for suggestions where to add.
Comment #16
bkosborneThis was a tricky one to debug, but doing so eventually led to me here today. Here's an example form that is affected by this bug which I think can be used as basis for a regression test of the fix:
In this example, if the select box has the first option selected AND the checkbox is checked, the textfield should be shown. However, on page load w/ Big Pipe enabled, checking the checkbox (which meets conditions) does NOT show the textfield. You have to uncheck and then recheck it before it finally works.
Big Pipe causes two more invocations of Drupal behaviors, resulting in a total of 3 invocations with the form items in the context. That's enough to cause issues with the logic with the 3 duplicate states behaviors defined.
Comment #17
feyp commentedI just closed #3383972: States JavaScript should use the once library, causes problems with Big Pipe as a duplicate of this issue. There is some information on how to reproduce with the contributed Webform module in the IS of that issue and MR with a similar but slightly different approach to fixing this.
Comment #19
mstrelan commentedEnabled
big_pipemodule on existingJavascriptStatesTest. Test-only job should show it failing.Comment #20
mstrelan commentedWell GitLab CI made a liar out of me. For some reason it decided to skip the test instead of running it and letting it fail. Attaching a patch to see what Drupal CI thinks.
FWIW this is the result when running the test-only changes locally:
Comment #21
smustgrave commentedHiding #20 so bot doesn't pick it up.
Going to post in gitlab channel but I see this test-only job failed correctly https://git.drupalcode.org/issue/drupal-3347144/-/jobs/471592
But change seems good, had to look up the param changes but looks good.
Comment #22
quietone commentedI'm triaging RTBC issues. I read the IS and the comments. I didn't find any unanswered questions or other work to do.
Leaving at RTBC.
Comment #24
catchCommitted/pushed to 11.x and cherry-picked to 10.2.x, thanks!
Comment #27
catchComment #29
attheshow commentedRelated regression ticket is here: https://www.drupal.org/project/drupal/issues/3416398
Comment #30
catchThe regression in #3416398: Regression on entity reference field states seems like it might be worse than the bug with big pipe that this fixed - I'm considering rolling this back in 11.x and 10.2.x, so we can try again.
Comment #31
bkosborneHmm, tricky. So it seems the problem is that states sometimes needs to be applied again because the dependents may have changed, right?
In that case, I guess we need a way for states behavior to replace the existing state that was there before so it doesn't create duplicate state definitions.
Comment #34
catchDiscussed this briefly with nod_ in slack and we both think reverting is probably the best approach here - more sites are still on 10.1.x than 10.2.x, so reverting the bug fixed here won't be a regression for them, but the regression introduced with be a new bug when those sites update. Also doesn't seem like there's an easy fix for this in either direction, we probably can't use once, and might need to make the states javascript re-entrant instead, no idea what that means in practice.
Comment #36
acbramley commentedRerolling and marking as needs tests to cover the bug found in #3416398: Regression on entity reference field states
Comment #37
sukr_s commentedThis issue is a duplicate of #3386191: #states not working correctly when built from a logical combination of multliple fields
Comment #38
mstrelan commentedIt looks like the fix in #3386191: #states not working correctly when built from a logical combination of multliple fields was the exact same fix that had already been committed and reverted in this issue. So I'm wondering if we are still concerned about the issues in #34? I'm guessing not since @node_ was the one who committed it. Perhaps credit should be transferred from this issue as well. Setting to PMNMI to see if #34 still needs addressing.
Comment #39
nod_let's take that on in #3468860: JS #states behavior does not have a detach method,
Comment #41
quietone commentedThe tests are being done in #3468860: JS #states behavior does not have a detach method
Comment #42
nod_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.