Problem/Motivation

The States API won't pick up the value of a select field with #multiple = TRUE option.

Steps to reproduce:
- Create two fields in a form with the following code:

  $form['dependee'] = array(
    '#type' => 'select',
    '#options' => array(
      'a' => 'Option A',
      'b' => 'Option B',
      'c' => 'Option C',
    ),
    '#multiple' => TRUE,
  );

  $form['dependent'] = array(
    '#type' => 'textfield',
    '#states' => array(
      'visible' => array(
        'select[name="dependee[]"]' => array('value' => array('a')),
      ),
    ),
  );

The dependent field will stay hidden regardless of the value of the dependee. This happens because the value of a multiple select field is an array, and States tries to compare it with the reference with a === operator, which returns always false.

Proposed resolution

Add a handler for arrays in states.Dependent.comparisons. This works with ANDed values:

'select[name="dependee[]"]' => array('value' => array('a', 'b')),

and with ORs as well (following the syntax proposed in #735528: FAPI #states: Fix conditionals to allow OR and XOR constructions):

'select[name="dependee[]"]' => array(array('value' => array('a')), array('value' => array('c')))

Remaining tasks

  1. Land #2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked so we have somewhere to put tests for this.
  2. Expand that test to cover this case.
  3. Upload test-only vs. full patch to verify test and fix.
  4. Further reviews/refinements.
  5. RTBC.
  6. Commit to D9/D8.
  7. Open follow-up issue to backport to D7.

User interface changes

This feature finally works as intended:

Before

After

API changes

N/A

Data model changes

N/A

Release notes snippet

TBD.

CommentFileSizeAuthor
#188 1149078-nr-bot.txt133 bytesneeds-review-queue-bot
#185 states-api-doesnt-work-with-multiselect-fields-1149078-185.patch11.77 KBericbellot
#184 states-api-doesnt-work-with-multiselect-fields-1149078-184.patch26.46 KBronaldtebrake
#173 1149078-nr-bot.txt98 bytesneeds-review-queue-bot
#172 drupal-n1149078-172-95x.patch12.28 KBdamienmckenna
#167 1149078-167.test-form-after-running.png31.11 KBdww
#161 1149078-161.patch1.03 KBarnaud-brugnon
#154 interdiff-153_154.txt692 bytesgauravvvv
#154 1149078-154.patch1.03 KBgauravvvv
#153 interdiff-151_153.txt692 bytesgauravvvv
#153 1149078-151.patch1 KBgauravvvv
#152 1149078-nr-bot.txt1.25 KBneeds-review-queue-bot
#151 interdiff_150-151.txt635 bytesakram khan
#151 1149078-151.patch1 KBakram khan
#150 interdiff_147-150.txt720 bytesakram khan
#150 1149078-150.patch1 KBakram khan
#147 1149078-147.patch1.09 KBgauravvvv
#144 1149078-144.patch2.09 KB_utsavsharma
#144 interdiff_142-144.txt3.69 KB_utsavsharma
#143 1149078-nr-bot.txt164 bytesneeds-review-queue-bot
#142 states-multiselect-1149078-142.patch4.02 KBcobadger
#132 1149078-132-FAIL.patch6.66 KBdanflanagan8
#131 states-multiselect-1149078-130.patch2.03 KBmarios anagnostopoulos
#130 states-multiselect-1149078-130.patch2.02 KBmarios anagnostopoulos
#129 states-multiselect-1149078-129.patch1.98 KBmarios anagnostopoulos
#112 syntax-error-unsupported-pseudo-selector.png348.34 KBesod
#109 states-multiselect-1149078-109.patch3.64 KBuzlov
#104 1149078-drupal-states_multiselect-104-drupal86.patch4.09 KBdaniel kulbe
#102 1149078-drupal-states_multiselect-102-drupal86.patch3.38 KBdalin
#101 1149078-drupal-states_multiselect-101-drupal86.patch3.41 KBdalin
#98 1149078-98.patch4.15 KBGrandmaGlassesRopeMan
#92 interdiff_85-92.txt3.01 KBheddn
#92 1149078-92.patch4.21 KBheddn
#85 1149078-85.patch2.66 KBjofitz
#83 git_bash screengrab.png7.78 KBdinesh18
#75 Stateinterdif.txt561 bytesPavan B S
#75 states_api_doesn_t_work-1149078-75.patch1.44 KBPavan B S
#69 interdiff-1149078-66-69.txt848 bytesgoz
#69 states_api_doesn_t_work-1149078-69.patch1.84 KBgoz
#66 states_multiple.tar_.gz1.5 KBgoz
#66 interdiff-1149078-54-66.txt963 bytesgoz
#66 states_api_doesn_t_work-1149078-66.patch1.89 KBgoz
#54 states_api_doesn_t_work-1149078-54.patch945 byteslegolasbo
#54 interdiff-52-54.txt495 byteslegolasbo
#54 interdiff-45-54.txt854 byteslegolasbo
#52 states_api_doesn_t_work-1149078-52.patch1.27 KBlegolasbo
#52 interdiff-45-52.txt0 byteslegolasbo
#48 after.png33.72 KBlegolasbo
#48 before.png31.31 KBlegolasbo
#45 states_api_doesn_t_work-1149078-45.patch1.33 KBjrb
#43 states_api_doesn_t_work-1149078-43.patch1.33 KBjrb
#40 0001-Fixed-multiple-select-fields.patch2.32 KBkuntyi
#37 interdiff-1149078-34-37.txt460 byteshimanshupathak3
#37 states_api_doesn_t_work-1149078-37.patch1.33 KBhimanshupathak3
#34 states-multi-select-fix-1149078-34.patch1.37 KBmgifford
#29 states-multi-select-fix-1149078-29.patch990 bytesmgifford
#23 states-multi-select-fix-1149078-22.patch997 bytespeterpoe
#19 states-multi-select-fix-1149078-19.patch1.04 KBwuinfo - bill wu
#19 interdiff.17.txt373 byteswuinfo - bill wu
#17 states-multi-select-fix-1149078-17.patch1.01 KBwuinfo - bill wu
#16 interdiff.10.txt952 byteswuinfo - bill wu
#16 states-multi-select-fix-1149078-16.patch1013 byteswuinfo - bill wu
#14 states-multi-select-fix-1149078-14.patch964 byteswuinfo - bill wu
#14 interdiff.10.txt1.17 KBwuinfo - bill wu
#10 states-multi-select-fix-1149078-10.patch1.08 KBwuinfo - bill wu
#3 states-multi-select-fix-1149078-3.patch974 bytesarcaneadam
#1 states-multiple-select-1149078-1.patch704 bytespeterpoe
states_multiple_select.patch703 bytespeterpoe

Issue fork drupal-1149078

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

peterpoe’s picture

StatusFileSize
new704 bytes

Reference and values array should have the same length.

Status: Needs review » Needs work

The last submitted patch, states-multiple-select-1149078-1.patch, failed testing.

arcaneadam’s picture

Status: Needs work » Needs review
StatusFileSize
new974 bytes

I've tweaked the patch above to make for nicer code along with adding comments. I think some discussion needs to be had about how to handle multi-selects though, because in the first patch it only returns true if the two arrays match exactly. Where as my patch will return true as long as the values given in #states are selected in the select box, even if there are additional values.

So for example if my form structure looks like this

 $form['test'] = array(
    '#type' => 'select',
    '#title' => t('Toggle'),
    '#multiple' => TRUE,
    '#options' => array('true' => 'True', 'false' => 'False'),
  );
  
  $form['works'] = array(
    '#title' => t('It works'),
    '#type' => 'textfield',
    '#states' => array(
      'visible' => array(
        ':input[name="test[]"]' => array('value' => array('true')),
      ),
    ),
  );

and in my select box i have "True' and 'False' both picked then my patch evaluates to true. I wonder if there doesn't need to be some sort of extra key in the state api to tell it to do exact or inclusive checking, though I think there is already another issue for that somewhere.

How it is right now I think this patch at least fixes a current problem and limitation with the states api.

arcaneadam’s picture

Also as a side note for anyone running into this issue and not wanting to patch core. You can sort of hack around this in a custom js using something similar to the following:

(function($) {
  Drupal.behaviors.optAdd = {
    attach: function() {
      var opt_add = {};
      opt_add.Dependent = {};
      opt_add.Dependent.comparisons = {
        'Array': function(reference, value) {
          //Make sure that value is an array, other wise we end up always evaling to true
          if(!( typeof (value) == 'object' && ( value instanceof Array))) {
            return false;
          }
          //We iterate through each of the values provided in the reference
          //and check that they all exist in the value array.
          //If even one doesn't then we return false. Otherwise return true.
          var arrayComplies = true;
          $.each(reference, function(key, val) {
            if($.inArray(val, value) < 0) {
              arrayComplies = false;
            }
          });
          return arrayComplies;
        },
      };
      var states = Drupal.states;
      $.extend(true, states, opt_add);
      Drupal.states = states;
    }
  }
})(jQuery);
pacufist’s picture

I faced this problem on Drupal 7.14.

After apply patch #3 all started work just perfect.

wuinfo - bill wu’s picture

Status: Needs review » Needs work
wuinfo - bill wu’s picture

Status: Needs work » Needs review

Patch applied if putting the patch under core folder. I will put the status to review and let bot test it first.

wuinfo - bill wu’s picture

Issue tags: -FAPI #states

Status: Needs review » Needs work
Issue tags: +FAPI #states

The last submitted patch, states-multi-select-fix-1149078-3.patch, failed testing.

wuinfo - bill wu’s picture

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

I can reproduce the original issue in the latest 8.x with following setup:

New Drupal8.x setup with latest code with command: git pull
Built a small module with custom form and code in #3 comment

Attached patch applies to 8.x with same code as #3.

In Drupal 7.16, I can reproduce the same issue and the code in #3 is also working.

wuinfo - bill wu’s picture

Status: Needs work » Needs review

change the status

star-szr’s picture

Thanks @wuinfo! We could move this even further by cleaning up the code comments a bit as per http://drupal.org/node/1354. At a glance, I can see the comments need a space after the //, need to be a complete sentence (end in a period), and should be wrapped at 80 characters (some wrap early).

wuinfo - bill wu’s picture

Assigned: Unassigned » wuinfo - bill wu

Code can be a little bit better, I will work on it.

wuinfo - bill wu’s picture

Assigned: wuinfo - bill wu » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.17 KB
new964 bytes

@Cottser comment and code are both changed. Review needed.

wuinfo - bill wu’s picture

+++ b/core/misc/states.jsundefined
@@ -75,6 +75,20 @@ states.Dependent.comparisons = {
+    $.each(reference, function(key, val) {
+      if ($.inArray(val, value) < 0) {
+        return false;
+      }
+    });

return false here just exit the each loop. So there is a bug in the code.

wuinfo - bill wu’s picture

StatusFileSize
new1013 bytes
new952 bytes

Here is a new patch which basically use #10's code and #14's comment.

wuinfo - bill wu’s picture

StatusFileSize
new1.01 KB

Quit the .each loop as early as possible by "return false;", according to http://api.jquery.com/each/

jelle_s’s picture

+++ b/core/misc/states.jsundefined
@@ -75,6 +75,22 @@ states.Dependent.comparisons = {
+      if ($.inArray(val, value) < 0) {
+        arrayComplies = false;
+        return false;

Maybe add a comment that this return false is to break the loop and not to actually return false. When I first read this patch I was thinking we could replace the return arrayComplies; with a return true; since we returned false in the loop anyways. (But then it hit me it isn't the actual return, but it's just to break the foreach).

wuinfo - bill wu’s picture

StatusFileSize
new373 bytes
new1.04 KB

Comment was added according #18

jlapp’s picture

I was able to reproduce this issue on Drupal 7.19 and manually applying the patch from #19 resolved it for me. It would be great to see this committed to 8.x and backported to 7.x.

nod_’s picture

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

use jQuery $.isArray() detecting arrays is something we don't want to deal with.
don't use $.each, make a filtered for loop
don't need $.inArray(); we can use .indexOf since we don't need to care about IE8 (patch for D7 will be different, that's fine).

Pre-emptively tagging for https://drupal.org/project/ie8

Antoine Vigneau’s picture

Hi,

I wake up this thread because I'm experimenting this issue on 7.21.

I want to have a #states selector matching all select element of a multi-value field. My field is an Entity Reference and the widget is a Multiple Selects List. But at the end, I normally could select all these elements using: #field-dependee-values .form-type-select select. I expect that the dependent reacts on all select elements of the dependee, in fact it reacts to nothing (always show).
The only things which works is #field-dependee-values .form-type-select select:first but it works only for the first select element.

Here is my #states declaration in a form_alter (it's in a node edit form):

  $form['field_dependent']['#states'] = array(
    'visible' => array(
      '#field-dependee-values .form-type-select select:first' => array( /* Here it selects only the first <select> tag, I would like to select all */
        array('value' => '1'),
        array('value' => '2'),
      ),
    ),
  );

The dependent must react to multiple values of the dependee, hence the multiple 'value' array.

I tried other kind of selector with the name too but the name attribute has this structure: name_field_dependee[und][0][target_id], so I tried select[name="name_field_dependee[][][]"], it doen't work. I applied the patch #19 too but the comparison was never detected as an Array.

peterpoe’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new997 bytes

Applied _nod's review (use for instead of $.each and indexOf instead of $.inArray).

hass’s picture

rdeboer’s picture

Would love to see this patch committed. This is quite a common use-case and has cause me a few head-aches and poor UX issues.

oostie’s picture

Status: Needs review » Reviewed & tested by the community

Works for me, can this patch be committed to core?

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 23: states-multi-select-fix-1149078-22.patch, failed testing.

Tobias Xy’s picture

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

Status: Needs work » Needs review
StatusFileSize
new990 bytes

reroll....

vaza18’s picture

These patches were not working for me with multiselect selector when default value was not defined.

It became working only after adding this code (set oldValue = false instead of null) in defaultTrigger function:

...
defaultTrigger: function (event, valueFn) {
    var oldValue = valueFn.call(this.element);
    if (!oldValue) {
      oldValue = false;
    }
...
muschpusch’s picture

Is it possible to use / test this functionality without patching core for D7? I extended / overwrote the 'Dependent.comparisons' function like mentioned in #4 but it doesn't seem to work.

mgifford’s picture

@vaza18 can you roll a new patch?

ufku’s picture

For multiple selects, the correct approach is to initiate the state value as undefined to make sure strict equality fails when null is returned as a value.

Need to change:

          // Initialize the value of this state.
          this.values[selector][state.name] = null;

to:

          // Initialize the value of this state.
          this.values[selector][state.name] = undefined;

I can't provide a patch now sorry.

mgifford’s picture

StatusFileSize
new1.37 KB

Ok, I added that @ufku - we just need folks to test it now.

nod_’s picture

Status: Needs review » Needs work
Issue tags: +JavaScript, +Novice

The following line should be replaced with Array.isArray(value):


+     if (!(typeof(value) === 'object' && (value instanceof Array))) {

and we could use some fancy Array function for the other piece of code, like [].every() or something.

himanshupathak3’s picture

Assigned: Unassigned » himanshupathak3
Issue tags: +SrijanSprintNight
himanshupathak3’s picture

Added first requirement in code. Added patch and interdiff for it.
@nod_ the second requirement for function every is not supported by this way [12, 5, 8, 130, 44].every(elem => elem >= 10);, is there some other way we can use that ?

himanshupathak3’s picture

Assigned: himanshupathak3 » Unassigned
Status: Needs work » Needs review
DrCord’s picture

I applied patch #37, it did not fix multiple selects for me :( I did apply it to drupal 7.38 though...)

kuntyi’s picture

StatusFileSize
new2.32 KB

Hi all,

I tried to fix this issue. I have added solution to add logic operator, you need to add array with operator to the end of the value array, look syntax:

$form['dependent'] = array(
'#type' => 'textfield',
'#states' => array(
'visible' => array(
'select[name="dependee[]"]' => array('value' => array('a', 'c', array('xor'))),
),
),
);

You can use next operators: and (default), or and xor.
Can someone test it?

Thanks.

Status: Needs review » Needs work

The last submitted patch, 40: 0001-Fixed-multiple-select-fields.patch, failed testing.

goz’s picture

I think we should focus on the #37 patch way to fix this issue.

@Kuntyi, your patch add a more complex and powerful solution, so may be we could talk about it in another issue. This current issue will fix the multiple select field issue, and your issue will add logic operator feature.

jrb’s picture

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

In #37, I think the Array.isArray(value) comparison added per the suggestion in #35 should actually be !Array.isArray(value) (i.e. *not* an array). After making this change, it works for me.

I've attached an updated patch.

Status: Needs review » Needs work

The last submitted patch, 43: states_api_doesn_t_work-1149078-43.patch, failed testing.

jrb’s picture

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

Rerolled #43 for latest core.

mgifford’s picture

Does this need the <h3>Why this should be an RC target</h3> info & RC phase evaluation table? Also there's the "rc target triage" tag.

Just trying to help this along.

legolasbo’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Novice +Contributed project blocker
Related issues: +#2635664: Make the hide/show of the other field work.

Removing the novice tag because I don't think there are any outstanding novice tasks remaining.

I've manually reviewed the patch. The only thing I can think of to improve this patch would be to return FALSE by default, Iterate over the values and return TRUE if they all exist. Besides that nitpick, the patch works like a charm and committing this patch would unblock #2635664: Make the hide/show of the other field work.. I therefor think that a change in logic should not hold back the resolution of this issue.

Landing this patch unblocks #2635664: Make the hide/show of the other field work., which is why I added the Contributed project blocker tag.

legolasbo’s picture

StatusFileSize
new31.31 KB
new33.72 KB

To really take this home I've hidden some irrelevant files and made some before/after screenshots.

legolasbo’s picture

Issue summary: View changes
alexpott’s picture

Version: 8.0.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Needs work

This really makes me wish we had frontend testing.

Also this fails our eslint validation with the following errors.

core/misc/states.js
   95:34  error    Inconsistently quoted property `Array` found                quote-props
   95:34  error    Properties shouldn't be quoted as all quotes are redundant  quote-props
   95:34  error    Inconsistently quoted property `Number` found               quote-props
  163:47  error    Unexpected use of undefined                                 no-undefined
alexpott’s picture

Version: 7.x-dev » 8.0.x-dev

Didn't mean to set to 7.x

legolasbo’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new0 bytes
new1.27 KB

Thanks for pointing to the eslint documentation, I updated my phpstorm config to also include eslint for future patches.

Attached patch fixes the eslint errors. Even though the changes should not change any behaviour I manually tested it again to make sure.

Back to RTBC

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs manual testing
+++ b/core/misc/states.js
@@ -145,9 +159,6 @@
-          // Initialize the value of this state.
-          this.values[selector][state.name] = null;
-

Given we don't have frontend testing I want to see some evidence of visual regression testing because of this. This was added in #735528: FAPI #states: Fix conditionals to allow OR and XOR constructions and it was changed from being self.values[selector][state.pristine] = undefined; so I think we might have broken the OR or XOR logic...

legolasbo’s picture

Status: Needs work » Needs review
StatusFileSize
new854 bytes
new495 bytes
new945 bytes
+++ b/core/misc/states.js
@@ -146,7 +160,7 @@
           // Initialize the value of this state.
-          this.values[selector][state.name] = null;
+          this.values[selector][state.name] = undefined;

After reading trough #735528: FAPI #states: Fix conditionals to allow OR and XOR constructions I came to the conclusion that this change in #45 was probably unneeded and not relevant for the functionality. This means that the eslint error was introduced without any reason and the offending line should not be removed, but reverted to it's original state.

I put my theory to the (manual) test and concluded that the change to the line in question can indeed be reverted without breaking the functionality added in #45. Attached you'll find a new patch which reverts the line in question back to the way it is in HEAD.

Anonymous’s picture

There is an issue if you pass integer values to be compared against each other.
if you map the integer values to strings then you get the correct results.

Array: function (reference, value) {
            // Make sure value is an array.
            if (!Array.isArray(value)) {
                return false;
            }
            // Convert all comparisons to strings for indexOf to work with integers comparing to strings
            reference = reference.map(String);
            value = value.map(String);
            // We iterate through each value provided in the reference. If all of them
            // exist in value array, we return true. Otherwise return false.
            for (var key in reference) {
                if (reference.hasOwnProperty(key) && value.indexOf(reference[key]) === -1) {
                    return false;
                }
            }
            return true;
        },

Because the default value of multiselects is null, the reevaluate passes right over it. Thinking that null is the same value as null.

I tried to come up with a solution but the best I can do is pass a default value in. That isn't a fix be any means.

EDIT: Fixed, just skip the null checks.

update: function (selector, state, value) {
            // Only act when the 'new' value is actually new.
            if (value !== this.values[selector][state.name] || $(selector).prop('multiple')) {
                this.values[selector][state.name] = value;
                this.reevaluate();
            }
        },
legolasbo’s picture

neoappt, could you roll a patch of your solution?

mtift’s picture

Status: Needs review » Needs work

Hmmm, none of the above solutions work for me. Although, I was having a problem just with checkbox example, such as the one mentioned on https://api.drupal.org/api/drupal/core%21includes%21common.inc/function/...

$form['toggle_me'] = array(
  '#type' => 'checkbox',
  '#title' => t('Tick this box to type'),
);
$form['settings'] = array(
  '#type' => 'textfield',
  '#states' => array(
    // Only show this field when the 'toggle_me' checkbox is enabled.
    'visible' => array(
      ':input[name="toggle_me"]' => array('checked' => TRUE),
    ),
  ),
);

So maybe this was the wrong place to post. Sorry.

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

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

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

jhedstrom’s picture

Issue tags: +Needs tests

We now have a javascript test base, so adding the 'needs tests' tag.

sukanya.ramakrishnan’s picture

Has a fix been applied to core for this issue?

Thanks,
Sukanya

deranga’s picture

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

Applied patch from comment #52 to states.js on Drupal 7.50 and this works as expected now for multi-valued select field.

Will this patch ever be rolled into an update of Drupal 7?

deranga’s picture

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

Apologies accidentally changed version number for issue.

legolasbo’s picture

@deranga,

I believe the fix will be backported to D7 after it get's committed to 8.1.x-dev

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.

sukanya.ramakrishnan’s picture

Can this issue be taken up again? i tried applying the patch, but it doesnt work for me. I think i am going wrong with the syntax for the states property. Can someone please put down the correct syntax for a multi select field so that i can try again. Basically i need one field to be visible based on multiple values chosen in a select field (or condition)

Thanks,
Sukanya

goz’s picture

Re-roll patch with updates from neoaptt in #55.
I also join module to help test (rename file to .tar.gz instead of .tar_.gz).

Manual tests look fine with #55 updates.

Still missing javascript test base as suggested by jhedstrom in #59.

goz’s picture

Status: Needs work » Needs review
goz’s picture

Assigned: Unassigned » goz
Status: Needs review » Needs work

I'm working on tests.

There is some updates to make to #54.

+++ b/core/misc/states.js
@@ -201,7 +218,7 @@
+      if (value !== this.values[selector][state.name] || $(selector).prop('multiple')) {

Multiple property should not be used to defined null default value. Default null value is an issue for #multiple property but also #size property.
Both are specific to select list but we should find another solution more generic.

I suggest to use $this->reevaluate() at the end of states.Dependent.prototype.initializeDependee, which force analyze states conditions and apply events.

goz’s picture

Assigned: goz » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.84 KB
new848 bytes

Finally, i'm not sure this issue is the place to add tests. Another issue in progress is covering #states tests #2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked so we should add #multiple tests there.

Following patch solve default null issue for both #multiple and #size attribute when i check in my browser, but mink seems to not be OK with that. Very strange, may be we should investigate in specific issue.

sukanya.ramakrishnan’s picture

Was finally able to get the patch working. Manual testing is fine for me.

Thanks
Sukanya

sukanya.ramakrishnan’s picture

Issue summary: View changes
droplet’s picture

  1. +++ b/core/misc/states.js
    @@ -103,6 +103,23 @@
    +      reference = reference.map(String);
    

    The next function returns when the condition is met. We need not loop over each item.

  2. +++ b/core/misc/states.js
    @@ -103,6 +103,23 @@
    +      for (var key in reference) {
    

    Considered Array.some

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.

leisurman’s picture

Ive tried patch 52 and 69, but its still not working

Pavan B S’s picture

StatusFileSize
new1.44 KB
new561 bytes
+++ b/core/misc/states.js
@@ -103,6 +103,23 @@
+      // Convert all comparisons to strings for indexOf to work with integers comparing to strings

Applied the #69 patch manually and fixed the coding standard error "Line is exceeding 80 characters".

Status: Needs review » Needs work

The last submitted patch, 75: states_api_doesn_t_work-1149078-75.patch, failed testing.

sukanya.ramakrishnan’s picture

@leisurman, I found that i had to clear the browser cache in addition to drush cr to get this working.. weird, but worth giving a try!

Thanks,
Sukanya

leisurman’s picture

@sukanya.ramakrishnan Which patch did you use #75. I have not tried that one.

leisurman’s picture

I cleared browser and drupal cache. Patch #75 did not work for me. I get this warning. warning php Warning: Invalid argument supplied for foreach() in conditional_fields_states_handler_select_multiple() (line 29 of /var/www/html/d818/modules/conditional_fields/conditional_fields.states.

I am using hook form alter, But I also tried the Conditional fields module, this is its issue:
https://www.drupal.org/node/2857718
This module works in Drupal 7 when the dependee field is a multiple select

sukanya.ramakrishnan’s picture

@leisurman, I used the one in 69. I did not try any other module. Are u sure your syntax is correct? i had issues with my syntax and after figuring out the correct syntax, i updated the description on this issue to show the correct one (The description was missing something before, i cant recollect). Please verify your syntax against the example in the description of this issue.

jhedstrom’s picture

dinesh18’s picture

I tried to apply patch mentioned in #75 and it is getting applied properly with 1 white space-errors.
Do we need reroll ?

dinesh18’s picture

StatusFileSize
new7.78 KB

here is the gitbash screenshot

droplet’s picture

Issue tags: -ie8, -Needs manual testing

It's better to fix #72 & #75 at the same time.

jofitz’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new2.66 KB

Re-rolled.

@droplet Can you clarify what you are requesting in #72, please?

Status: Needs review » Needs work

The last submitted patch, 85: 1149078-85.patch, failed testing. View results

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.

sukanya.ramakrishnan’s picture

Status: Needs work » Needs review

Updating status to kick off tests for the 8.4 patch

GrandmaGlassesRopeMan’s picture

Status: Needs review » Needs work
  1. +++ b/core/misc/states.es6.js
    @@ -100,6 +100,24 @@
    +      // Convert all comparisons to strings for indexOf to work with integers
    +      // comparing to strings
    

    Multiline comment format.

  2. +++ b/core/misc/states.es6.js
    @@ -100,6 +100,24 @@
    +      // We iterate through each value provided in the reference. If all of them
    +      // exist in value array, we return true. Otherwise return false.
    

    Multiline comment format

  3. +++ b/core/misc/states.es6.js
    @@ -100,6 +100,24 @@
    +      for (var key in reference) {
    

    Don't use `for in`. Use Object.{keys,values,entries}

  4. +++ b/core/misc/states.es6.js
    @@ -100,6 +100,24 @@
    +        if (reference.hasOwnProperty(key) && value.indexOf(reference[key]) === -1) {
    

    Remove `hasOwnProperty` check.

  5. +++ b/core/misc/states.es6.js
    @@ -153,6 +171,10 @@
    +          // Reevaluate conditions and trigger to be sure default value like
    +          // null is handled.
    

    Multiline comment format.

heddn’s picture

It isn't clear what is needed with the multi-line comments. It seems that both C style and C++ are both allowed: https://www.drupal.org/docs/develop/standards/javascript/javascript-codi...

droplet’s picture

C++ comment style is preferred to use inside the function. We missed some complete docs I thought.

https://www.drupal.org/node/1354#inline

Blocker of this issue: Missing tests

heddn’s picture

Status: Needs work » Needs review
StatusFileSize
new4.21 KB
new3.01 KB

I think this fixes the feedback from #89. And I did successful manual testing using the following. Even the red asterisks for the required showed up.

      '#states' => [
        // Show the settings if 'orders' has been selected for 'exported_content'.
        'visible' => [
          ':input[name="exported_content"]' => ['value' => 'orders'],
        ],
        'required' => [
          ':input[name="exported_content"]' => ['value' => 'orders'],
        ],
      ],
heddn’s picture

Status: Needs review » Needs work

Actually, scratch that. I had temporarily removed '#multiple' from the code. It still isn't working.

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

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should 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.

jrockowitz’s picture

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

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.

igalafate’s picture

#92 patch doesn't apply anymore after I have updated to 8.6. Has anyone run into the same problem?

GrandmaGlassesRopeMan’s picture

StatusFileSize
new4.15 KB

- reroll for 8.7.x

GrandmaGlassesRopeMan’s picture

  1. +++ b/core/misc/states.es6.js
    @@ -135,6 +135,24 @@
    +      // Convert all comparisons to strings for indexOf to work with integers
    +      // comparing to strings.
    

    Since we are following AirBnB coding standards, they suggest using /** ... */ for multiline comments.

  2. +++ b/core/misc/states.es6.js
    @@ -135,6 +135,24 @@
    +      for (var [key, referenceValue] of Object.entries(reference)) {
    +        if (value.indexOf(reference[key]) === -1) {
    +          return false;
    +        }
    +      }
    

    Coding standards explicitly forbid using for...in loops. Use an actual iterator instead.

    Additionally, Object.entires() no Internet Explorer support. You'll need to use Object.keys{,values} instead. Somewhat related, there is ongoing discussion around adding polyfill support for missing features in JavaScript here, #2985495: JS: Polyfills support

arnaud-brugnon’s picture

If you are not patient and you still want to add multiple values,
You should check this link https://evolvingweb.ca/blog/extending-form-api-states-regular-expressions

It's for Drupal 7 but it works for D8 with some adjustment.

dalin’s picture

Here's a re-roll of the patch that applies to 8.6.

This does not address the issues brought up in #99.

dalin’s picture

StatusFileSize
new3.38 KB

Oops, re-roll the patch for 8.6 with the correct git root.

daniel kulbe’s picture

This does currently not work due Error:
ReferenceError: _slicedToArray is not defined

daniel kulbe’s picture

Updated patch

ckidow’s picture

It seems that the Patch #80 from following issue solves this issue as well: https://www.drupal.org/node/1091852

attiks’s picture

#105 Patch from #1091852-80: Display Bug when using #states (Forms API) with Ajax Request didn't work for me, but patch from #104 works with the following code

    $form['field_countries']['#states'] = [
      'visible' => [
        '#edit-field-document-types' => [
          ['value' => ['13']],
          ['value' => ['14']],
        ],
      ],
    ];
pancho’s picture

Patch #104 seems to fail 1 out of 3 tests of the Nightwatch JS statesTest, but otherwise passes all tests.

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.

uzlov’s picture

Status: Needs work » Needs review
Issue tags: +dckyiv2019
StatusFileSize
new3.64 KB

Fixed issue, tested with another types of depended elements.
Like:

    $form['select'] = [
      '#type' => 'select',
      '#title' => 'select 1',
      '#options' => [0 => 0, 1 => 1, 2 => 2],
    ];
    $form['number'] = [
      '#type' => 'number',
      '#title' => 'enter 1',
    ];
    $form['textfield'] = [
      '#type' => 'textfield',
      '#title' => 'textfield',
      '#states' => [
        'visible' => [
          [':input[name="select"]' => ['value' => '1']],
          'or',
          [':input[name="number"]' => ['value' => '1']],
        ],
      ],
    ];

Removed:

+        // Reevaluate conditions and trigger to be sure default value like
+        // null is handled.
+        this.reevaluate();

Please, check

esod’s picture

Both #109 and #102 apply cleanly to our Drupal 8.6.16 system. Neither patch fixes the issue, but we're using Chosen, which may be interfering.

andrewmriv’s picture

Can also confirm that #104 did not work for me on Drupal 8.7. Also have Chosen enabled, though so I may also just be affected by that.

esod’s picture

StatusFileSize
new348.34 KB

Using this form code with or without any patches applied :

    $element['my_field'] = [
      '#title' => $this->t('Title'),
      '#type' => 'checkbox',
      '#default_value' => $items->my_field,
      '#description' => $this->t('Description goes here.'),
      '#weight' => 1,
      '#states' => [
        'visible' => [
          ':select[name="field_my_multi_select_field[]"]' => [['value' => 'my_value']],
        ],
      ],
    ];

I get this error:

Syntax error unsupported pseudo selector

esod’s picture

Never mind the last comment. It should be 'select[name="field_my_multi_select_field[]"]', not ':select[name="field_my_multi_select_field[]"]'

:select must be a pseudo selector.

Patch #109 still doesn't work. :(

pfenriquez’s picture

@esod

Patch #109 worked for me (using also Chosen), but you must pass the value as an array of 'value'


  $element['my_field'] = [
      '#title' => $this->t('Title'),
      '#type' => 'checkbox',
      '#default_value' => $items->my_field,
      '#description' => $this->t('Description goes here.'),
      '#weight' => 1,
      '#states' => [
        'visible' => [
          'select[name="field_my_multi_select_field[]"]' => [['value' => ['my_value']]],
        ],
      ],
    ];

Please note the ['my_value']

Best

edit: removed pseudo selector for example.

pfenriquez’s picture

Status: Needs review » Reviewed & tested by the community
esod’s picture

@Penef. Thanks. Yes the patch does indeed work when you pass the value as an array of 'value'. Hooray!

The tip off was the three close brackets after my_value on the select line.

    ...
          'select[name="field_my_multi_select_field[]"]' => [['value' => ['my_value']]],
    ...
esod’s picture

The patch still applies cleanly to Drupal 8.7.7, but the patch has stopped working when using a <select> tag.

esod’s picture

Actually, never mind my last comment. We had another, unrelated js issue on our site. Patch works fine for us in Drupal 8.7.7!

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.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 109: states-multiselect-1149078-109.patch, failed testing. View results

jungle’s picture

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

Might be a random failure

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.

phjou’s picture

It seems to work for a specific value, but how do you make it work to check that it is not empty?
I tried multiple stuff and nothing seems to work.

This one would seem logical for me, but it does not work.

          '#states' => [
            'invisible' => [
              'select[name="custom_select[]"]' => [
                ['value' => []],
              ],
            ],
          ],
dww’s picture

Title: States API doesn't work with multiple select fields » [PP-1] States API doesn't work with multiple select fields
Issue summary: View changes
Status: Needs review » Postponed
Issue tags: +Bug Smash Initiative
Related issues: +#2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked

This issue 'Needs tests' before it could be committed.
We have an RTBC core issue that adds a bunch of great #states tests: #2702233: [backport] Add JavaScript tests for Form API #states: required, visible, invisible, expanded, checked, unchecked
That would be the perfect place to add the tests that this issue sorely needs.
Therefore, this should be postponed until that one lands.

Also, giving this issue a proper summary with accurate 'Remaining tasks' section.

Thanks!
-Derek

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.

kevin.dutra’s picture

Title: [PP-1] States API doesn't work with multiple select fields » States API doesn't work with multiple select fields
Status: Postponed » Needs work

The issue this was postponed on appears to have been committed, so returning to "needs work" for the addition of tests.

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.

leon kessler’s picture

I'm having the same issue as #123, I can't get this to work when targeting an empty multiple value select field.
I've tried
['value' => []]
['value' => '']
['empty' => TRUE]
['filled' => FALSE]

None of these work.

marios anagnostopoulos’s picture

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

The way #109 is implemented, if the reference is empty (E.g ['value' => []]), the condition returned is always true, regardless if the given value (actual field selections) is empty or not, because it never goes through the loop.

I uploaded a different patch using the Array.prototype.every for executing the loop, which seems to handle the issue.

It does not work with ['value' => ''] | ['empty' => TRUE] | ['filled' => FALSE], like the #109 does not.
For the ['value' => ''] it shouldn't anyway since it would be semantically wrong. Now if we should support the empty and filled options, is debatable, but I think that ['value' => []] should cover it.

Let me know if the patch solves the issue in your projects as well, or if it needs more tuning.

marios anagnostopoulos’s picture

StatusFileSize
new2.02 KB

Had to change the paths for the patch to apply, my bad.

marios anagnostopoulos’s picture

StatusFileSize
new2.03 KB

Fixed an issue with prettier

danflanagan8’s picture

StatusFileSize
new6.66 KB

Here's a test-only patch to expose the bug and then work against. It has a couple especially notable cases.

1. There's one for the empty value, which is a case that there are several comments about.

    $form['item_visible_when_multiple_select_trigger_has_no_value'] = [
      '#type' => 'item',
      '#title' => 'Item visible when multiple select trigger has no value',
      '#states' => [
        'visible' => [
          ':input[name="multiple_select_trigger[]"]' => ['value' => []],
        ],
      ],
    ];

The patch in 109 cannot handle this. The patch in 130 handles this well.

2. There's a case for an OR condition.

    $form['textfield_visible_when_multiple_select_trigger_has_value2_or_value3'] = [
      '#type' => 'textfield',
      '#title' => 'Textfield visible when multiple select trigger has value2 or value3',
      '#states' => [
        'visible' => [
          ':input[name="multiple_select_trigger[]"]' => [
            ['value' => ['value2']],
            ['value' => ['value3']],
          ],
        ],
      ],
    ];

This OR case especially is interesting. I'm not sure if that's the right syntax or if there even is an agreed upon syntax. The patch in 109 makes this work like an OR. The patch in 130 makes this work like an XOR.

The test performs an assertion as if it should work like OR. It's possible that's an incorrect expectation on my part. I can't say I'm an expert on #states.

Status: Needs review » Needs work

The last submitted patch, 132: 1149078-132-FAIL.patch, failed testing. View results

marios anagnostopoulos’s picture

Indeed this is an issue. This syntax should not work like XOR (I will look into it when I find the time).
The thing is that multi-value fields are new to the states API I think and should have a bit more care in their handling.

We should introduce a way to define if we want the value, given in the reference array, to be strictly compared or not.

This problem extends also to cases like this.

Let's say we have a multi-select field and set some state to check.
['value' => ['val1', 'val2']]
The way the code works atm dictates that the condition is fulfilled if AT LEAST BOTH of these two values are present. Meaning that
['val1', 'val2', 'val3'] input will also fulfill the condition. It is not clear that this is an intended behavior (Not to me at least).

We should address this issue first IMO and then handle the conjunction between multiple conditions.

danflanagan8’s picture

It is not clear that this is an intended behavior (Not to me at least).

It is not clear to me either. :)

The thing is that multi-value fields are new to the states API...We should address this issue first IMO and then handle the conjunction between multiple conditions.

Does that mean we need to get a subsystem maintainer review? I'm going to add that tag. We can remove it if I'm wrong!

I think as this issue moves along, we'll need to add a few test cases and/or modify the expectations of the existing ones, but I'm going to remove the Needs tests tag since the tests exist, even if they may require some tweaks.

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.

stijndmd’s picture

I'm trying this patch in combination with inline entity forms.

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 *
 * @param array $entity_form
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 */
function MY_MODULE_inline_entity_form_entity_form_alter(array &$entity_form, FormStateInterface &$form_state) {
  $parents = $entity_form['#parents'];
  $identifier = $parents[0].'['.implode('][', array_slice($parents, 1)).']';

  // Visibility (of my multiple select field) depending on a regular select field with max 1 value. This works.
  $entity_form['field_two']['#states'] = [
    'visible' => [
      ':input[name="'.$identifier.'[field_one]"]' => ['value' => 'value_a'],
    ],
  ];
  // Here, visibility should be dependant on the value of my multiple select field. I don't get this to work.
  $entity_form['field_three']['#states'] = [
    'visible' => [
      ':input[name="'.$identifier.'[field_two[]]"]' => [['value' => ['value_b']]],
    ],
  ];
}

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.

hmendes’s picture

Status: Needs work » Needs review

I tested the patch from #131 using the custom fields of the IS and doing a few changes to test.

    $form['dependee'] = [
      '#type' => 'select',
      '#options' => [
        'a' => t('Option A'),
        'b' => t('Option B'),
        'c' => t('Option C'),
      ],
      '#multiple' => TRUE,
    ];

    $form['dependent'] = [
      '#type' => 'textfield',
      '#states' => [
        'visible' => [
          'select[name="dependee[]"]' => ['value' => ['a']],
        ],
      ],
    ];

Here are my results:
1:
'select[name="dependee[]"]' => ['value' => ['a']],
It will only show the field if I select EXACTLY A.
Selecting 2 (doesn't matter which options are selected) or 3 options -> is not showing the field

2:
'select[name="dependee[]"]' => ['value' => ['a', 'b']],
It will only show the field if I select EXACTLY A and B
Selecting 2 (doesn't matter which options are selected) or 3 options -> is not showing the field

3:
'select[name="dependee[]"]' => ['value' => ['c', 'a', 'b']],
It will only show the field if I select EXACTLY A, B and C

4:
'select[name="dependee[]"]'=> [['value' => ['a']], ['value' => ['b']]],
It will only show the field if I select EXACTLY A or EXACTLY B (if I select A and B it won't show the field)

5:
'select[name="dependee[]"]'=> [['value' => ['a']], ['value' => ['b']], ['value' => ['c']]],
It will only show the field if I select EXACTLY A, EXACTLY B or EXACTLY C (if I select two or three options at the same time it won't show the field)

Tested all tests above but now setting a default value for the field -> did not interfere with the result

So I didn't understand about the XOR behavior... Did i do some wrong testing?

stijndmd’s picture

I can confirm those results from https://www.drupal.org/project/drupal/issues/1149078#comment-14590562, as explained in https://www.drupal.org/project/drupal/issues/1149078#comment-14279315

Seems like this can not be expected behaviour since you want subfields to appear from the moment their selector has been tagged in the multi-select field used for the conditions. Still works with patch from #109 which still applies to core 9.3.

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.

cobadger’s picture

StatusFileSize
new4.02 KB

Attaching patch against Drupal 9.5.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new164 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.

_utsavsharma’s picture

StatusFileSize
new3.69 KB
new2.09 KB

Tried to fix CCF for 9.5.x in #142.

abelass’s picture

#144 doesn't work on 9.4.11
#130 does work for me

abelpzl’s picture

#142 does work for me in 9.5.3 with php 7.4

gauravvvv’s picture

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

I have attached patch for 10.1.x. none of the above patch is applying to 10.1.x. So not attaching interdiff. please review

ysamoylenko’s picture

Confirming that https://www.drupal.org/project/drupal/issues/1149078#comment-14271390 works correctly with empty values on 9.5.3.

nod_’s picture

Status: Needs review » Needs work

I don't have a good idea about what should be the expected behavior, and I don't have the time to get into it this weekend. One the other hand, one small review:

  1. +++ b/core/misc/states.js
    @@ -159,6 +159,24 @@
    +      Object.entries(reference).forEach(([key, referenceValue]) => {
    

    key is never used, Object.values() would be more appropriate than entries.

  2. +++ b/core/misc/states.js
    @@ -159,6 +159,24 @@
    +        if (value.indexOf(referenceValue) === -1) {
    +          return false;
    +        }
    +      });
    +      return true;
    

    This could be simplified by using includes()

Also not sure what that loop is doing, returing true or false inside the foreach does not do anything. I see #142 was using a for loop, in that case returning true/false would make sense. Not with forEach().

I would definitely expect some tests cases here just to make sure we agree on the behavior.

akram khan’s picture

StatusFileSize
new1 KB
new720 bytes

added updated patch address #149

akram khan’s picture

Status: Needs work » Needs review
StatusFileSize
new1 KB
new635 bytes

try to fixed CCF #150

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.25 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 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.

gauravvvv’s picture

Status: Needs work » Needs review
StatusFileSize
new1 KB
new692 bytes

Addressed #149, attached interdiff for same. please review

gauravvvv’s picture

StatusFileSize
new1.03 KB
new692 bytes

Fixed build issue.

gauravvvv’s picture

Wrong patch uploaded in #153. Updated the patch in #154.

saurabh-2k17’s picture

#144 did not work in my case. I later used #142 which fixed the problem. My Drupal Core version is 9.5.7

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

vladimiraus’s picture

Switching to MR.

neslee canil pinto’s picture

@VladimirAus Object.values will give referenceValue undefined, inside if we use Object.entries it will work fine with key, value pair

arnaud-brugnon’s picture

StatusFileSize
new1.03 KB

Improve patch based on #160 comments

By the way, it works fine for me.

smustgrave’s picture

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

Seems tests have been lost.

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.

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

vasike’s picture

Status: Needs work » Needs review

Updated the MR - trying to add the tests from #132

So:
- Add tests
- Change compare - The arrays values should match - it should work also for empty arrays.
- Fix a test ... i think the OR check there was not right if value2 OR value3 doesn't mean if should be displayed when both value2 and value3 selected.
For OR case we should something if (value2 and value3) OR (value7 and value32)

Note: i only used tests to check the "solution" ... i didn't test manually.

dww’s picture

Status: Needs review » Needs work

Thanks, great progress!

About out the door for a few AFK meetings, but I'll try to look more closely when I'm back. Super quick skim finds some nits with the tests (wrong comments, etc). Also, the other #states tests in these files are now starting to do:

  1. Setup initial state + validate
  2. Trigger the change
  3. Check all the changes
  4. Revert the trigger change
  5. Re-verify the initial state is back

The test in the MR is currently stopping at step 3 (like many, but not all of the other protected helpers)...

dww’s picture

StatusFileSize
new31.11 KB

Ugh, that's super annoying. 😢 I worked on this locally. To my great surprise, 2 of the "initial state" assertions are failing after I remove the values in the multi-select trigger:

  1. $this->assertTrue($item_visible_no_value->isVisible());
  2. $this->assertFalse($textfield_visible_value2_and_value3->isVisible());

If I comment those out, the test passes. If either are still present, the test fails. However, when I inspect the HTML output of the failing page, I see it looks like it's working as expected:

JavascriptStatesForm HTML output after restoring initial trigger state

The multi-select indeed has no values, and the only thing visible in the section of tested elements is what $item_visible_no_value points to. The rest of the test is working fine. Manually testing the multi-select trigger from this HTML result page and all the JS seems to be working as expected, too.

I'm not sure this is actually a bug in the states code -- it could just be a bug in the test. But I'm out of time for today to keep digging.

Sorry,
-Derek

dww’s picture

Grr, phpcs didn't like how I commented out the failing assertions. 😢

I fixed that and pushed a commit with the failing assertions included. That run should fail.

Pushed another where I properly commented out. core/scripts/dev/commit-code-check.sh is now passing locally. 😅

Also rebased to the latest 10.1.x branch. We probably need to change the MR to point to 11.x for now. However, I just verified that the MR plain diff applies cleanly to the 11.x branch, too (as expected), so I'm not going to mess with trying to get the MR target branch changed (which I don't have permissions to do).

vasike’s picture

i confirm that the js is working properly ... but it seems the $trigger->setValue([]); doesn't work properly.

So what should we do ... find another way to "deselect" the multiple selection?

What about the chasing this "odd case" in a separate issue.
And try to commit the "current solution"?

dww’s picture

Yeah, I hate holding up a fix in the quest for "perfect" tests. Definitely open to moving the last bits to a follow-up...

However, in more closely inspecting the HTML output of the tested page, the initial state's markup for the item looks like this:

<div data-drupal-states="{&quot;visible&quot;:{&quot;select[name=\u0022multiple_select_trigger[]\u0022]&quot;:{&quot;value&quot;:[]}}}" id="edit-item-visible-when-multiple-select-trigger-has-no-value" class="js-form-item form-item js-form-type-item form-item-item-visible-when-multiple-select-trigger-has-no-value js-form-item-item-visible-when-multiple-select-trigger-has-no-value">
      <label for="edit-item-visible-when-multiple-select-trigger-has-no-value">Item visible when multiple select trigger has no value</label>
        
        </div>

After the test fails, the final output page has this for the element:

<div data-drupal-states="{&quot;visible&quot;:{&quot;select[name=\u0022multiple_select_trigger[]\u0022]&quot;:{&quot;value&quot;:[]}}}" id="edit-item-visible-when-multiple-select-trigger-has-no-value" class="js-form-item form-item js-form-type-item form-item-item-visible-when-multiple-select-trigger-has-no-value js-form-item-item-visible-when-multiple-select-trigger-has-no-value" style="">
      <label for="edit-item-visible-when-multiple-select-trigger-has-no-value">Item visible when multiple select trigger has no value</label>
        
        </div>

The only difference is that the one that's failing the test assertion includes this: style="". That shouldn't matter, but maybe it does?

I'll also note that while inspecting the HTML on the failed test output, I'm getting 5 of these:

Incorrect use of <label for=FORM_ELEMENT>

The label's for attribute doesn't match any element id. This might prevent the browser from correctly autofilling the form and accessibility tools from working correctly.

To fix this issue, make sure the label's for attribute references the correct id of a form field.

All 5 of the affected nodes are the item elements. That seems completely unrelated to this issue or bug, but wanted to note it here. Probably we need a follow-up to investigate this part, too.

dww’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

Thanks for the review and fixes. Almost there! I opened #3367310: Get all assertions working in JavascriptStatesTest::doMultipleSelectTriggerTests() as the follow-up to sort out the final test weirdness, and pushed a commit to add the @see comment pointing to it as part of the @todo.

I believe all feedback is now addressed, so this is ready for (hopefully final?) review. Removing the "Needs tests" tag, since that's now done.

Thanks again!
-Derek

p.s. Before commit, this issue definitely needs a review of issue credits. There are a bunch of 1-off patches in here that probably shouldn't get credits, and a couple of folks who commented a lot but haven't uploaded anything who might need to be credited. If I have a chance later today, I'll work on this, but if I don't get to it, someone needs to before this is truly ready.

damienmckenna’s picture

StatusFileSize
new12.28 KB

The latest merge request in patch format for 9.5.x.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new98 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch 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.

nod_’s picture

Status: Needs work » Needs review
sukanya.ramakrishnan’s picture

Slightly confused here, I am looking for a solution for the scenario 4 in this comment
https://www.drupal.org/project/drupal/issues/1149078#comment-14590562

'select[name="dependee[]"]'=> [['value' => ['a']], ['value' => ['b']]],
It will only show the field if I select EXACTLY A or EXACTLY B (if I select A and B it won't show the field)

I need the field to be displayed if I select A and B (in addition to other values not in the conditions) . I applied the latest patch and still see the issue. Has this issue been addressed in the latest patch/ am i missing something or is it going to be addressed separately?

Thanks,
Sukanya

vasike’s picture

@sukanya.ramakrishnan maybe at first sight
For
'select[name="dependee[]"]'=> [['value' => ['a']], ['value' => ['b']]],
We expect to work also for both a and b selected
But it's not true ... because it's about the value(s) of the element.

And actually we have:
[a,b] !== [a] and [a,b] !== [b]

Which means that maybe you need something different like
'select[name="dependee[]"]'=> [['value' => ['a']], ['value' => ['b'], ['value' => ['a', 'b']]],
To cover all the Multiple element value(s) scenarios.

P.S. remember, we're talking about MULTIPLE and we're using SET of Values ... not Parts of Values

i hope i got it right :).

smustgrave’s picture

Status: Needs review » Needs work

Still needs submaintainer review but @dww could the MR be updated for 11.x please?

mukhtarm’s picture

Any idea on how to fix this issue, I applied the MR (https://git.drupalcode.org/project/drupal/-/merge_requests/3805/diffs) and still doesn't resolve the issue.

for eg:

$form['payment_methods'] = [
      '#type' => 'select',
      '#title' => $this->t('Select the payment methods'),
      '#options' => [
        'cvs' => $this->t('convenience stores'),
        'credit' => $this->t('credit card'),
        'payeasy' => $this->t('Pay-easy'),
      ],
      '#multiple' => TRUE,
      '#required' => TRUE,
      '#attributes' => [
        'id' => 'payment_methods',
        'name' => 'payment_methods',
      ],
    ];

    $form['cvs'] = array(
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => t('Convenience Store Options'),
      '#description' => $this->t('<b>Convenience Store informations are taken only if the cvs payment method selected.</b>'),
      '#attributes' => [
        'id' => 'cvs_fieldset'
      ],
      '#states' => array(
        'visible' => array(
          ':input[name="configuration[link_type_plus][payment_methods][]"]' => ['value' => 'cvs'],
        ),
      )
    );

Why i given the name so?: when inspected the element the name for the element displayed so. Also when giving name="payment_methods][]" also not working.

abelass’s picture

Is there any solution for 10.1.5 ?

vasike’s picture

@MukhtarM i think you're trying "wrong selector"
':input[name=..."
when here it's about select
'select[name=..."

could you, please, check?
thanks

vasike’s picture

Status: Needs work » Needs review

new MR for 11.x available ... all updated and "Green", so i think we're back to Needs Review

mukhtarm’s picture

Thanks @vasike, The issue is fixed for me after applied the latest MR(https://git.drupalcode.org/project/drupal/-/compare/308e696f76fc33d6a5d8...).

Exactly was in the section:

Array(reference, value) {
      // Make sure value is an array.
      if (!Array.isArray(value)) {
        return false;
      }
      // Convert all comparisons to strings for indexOf to work with integers
      // comparing to strings.
      reference = reference.map(String);
      value = value.map(String);
      // We iterate through each value provided in the reference. If all of them
      // exist in value array, we return true. Otherwise return false.
      return Object.entries(reference).every(([key, referenceValue]) =>
        value.includes(referenceValue),
      );
    },

Correct solution for me is:

   '#states' => array(
        'visible' => array(
          'select[name="configuration[link_type_plus][payment_methods][]"]' =>   [['value' => ['cvs']], ['value' => ['payeasy']]],
        ),
      )

if that helps anybody in future. This will show and hide the fieldset when either 'cvs' or 'payeasy' is selected

ronaldtebrake’s picture

Can confirm for us https://git.drupalcode.org/project/drupal/-/merge_requests/3805 also did the trick (for D10.x)
I've attached a static patch of the current state of the MR for CI/CD purposes.

ericbellot’s picture

For me, on Drupal 10.1.6, the patch #184 does not work completely. I had to go back to version #183 of states.js.

Sorry, my patch is useless. The patch #161 works correctly on Drupal 10.1.

smustgrave’s picture

Assigned: Unassigned » nod_

Assigning to javascript submaintainer.

nod_’s picture

Assigned: nod_ » Unassigned
Status: Needs review » Reviewed & tested by the community

Works for me, it's simple enough and does the job advertised. Thanks for the tests too!

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new133 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. 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.

vasike’s picture

Status: Needs work » Reviewed & tested by the community

it seems we need to hide the patch from #185
back to previous Status ... RTBC

nod_’s picture

Status: Reviewed & tested by the community » Needs work

There is a todo left in the tests code

nod_’s picture

Status: Needs work » Reviewed & tested by the community

  • nod_ committed f6be8531 on 11.x
    Issue #1149078 by vasike, wuinfo - Bill Wu, dww, Gauravvvv, Marios...

  • nod_ committed 5e5839ab on 10.3.x
    Issue #1149078 by vasike, wuinfo - Bill Wu, dww, Gauravvvv, Marios...

  • nod_ committed a44ba4db on 10.2.x
    Issue #1149078 by vasike, wuinfo - Bill Wu, dww, Gauravvvv, Marios...

nod_’s picture

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

Thanks everyone for keeping this going for so long, it's finally in :)

Committed f6be853 and pushed to 11.x. Thanks! Backported to 10.2.x and 10.3.x

dww’s picture

whoot, thanks!

Status: Fixed » Closed (fixed)

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

n.dhuygelaere’s picture

Sorry, but the last version of Drupal 10.3.1 break all my "select" based conditional fields.
My conditional fields works well on Drupal 10.2.6

Here an extract from my form where the field_child is visible when the taxonomy term (tid:1234) is selected

$form['field_child']['#states'] =  [
            'visible' => [
                ['select[name="field_parent[]"]' => [value=>'1234']],
            ],
        ];
n.dhuygelaere’s picture

I answer to myself. finally i've solved my issue by fixing 2 points:

The first point was a mistake from my side : the "value" used in the definition must be a "string". In my code, i used an entity reference id defined as an integer.

The second point was linked to my select field defined as a "multiple" one. To address this point it's necessery to alter the "compare" function of core/misc/states.js. I add this js library into my module

/**
 * @file
 * Extends core/misc/states.js.
 */
 
(function($) {

    //correction core : can't add a #states on a select with multiple = true
    function _compareCustom(a, b) {
        if (a !== "undefined" && typeof b === 'object' && b instanceof Array) {
            if (b.includes(a)) {
              return true;
            }
        }

        if (a === b) {
            return typeof a === 'undefined' ? a : true;
        }

        return typeof a === 'undefined' || typeof b === 'undefined';
    }

    //hack : surcharge function compare from core/states.js to use _compareCustom instead of _compare2
    Drupal.states.Dependent.prototype.compare = function compare(reference, selector, state) {
        var value = this.values[selector][state.name];
        if (reference.constructor.name in Drupal.states.Dependent.comparisons) {
          return Drupal.states.Dependent.comparisons[reference.constructor.name](reference, value);
        }

        return _compareCustom(reference, value);
      };

})(jQuery);

This solution works with all drupal version from 8.x to 10.3.1.