I'm not sure that this is an actual regression of #735528: FAPI #states: Fix conditionals to allow OR and XOR constructions but some of the code that was added in that issue is part of the problem. So marking as a regression.

Situation: I have created a field formatter settings form that contains a.o.:

  $name_prefix = 'fields[' . $field['field_name'] . '][settings_edit_form][settings]';
  $element = array();
  $element['setting1'] = array(
    '#type' => 'select',
    '#title' => t('Title'),
    '#default_value' => $settings['setting1'],
    '#options' => array(
      'a' => t('A'),
      'b' => t('B'),
      'c' => t('C'),
      'd' => t('D'),
    ),
    '#required' => FALSE,
  );
  $name = $name_prefix . '[$setting1]';
  $element['setting2'] = array(
    '#type' => 'textfield',
    '#title' => t('Title2'),
    '#default_value' => $settings['setting2'],
    '#required' => $settings['setting1'] === 'c' || $settings['setting1'] === 'd',
    '#states' => array(
      'enabled'  => array(":input[name='$name']" => array(array('value' => 'c'), array('value' => 'd'))),
      'required' => array(":input[name='$name']" => array(array('value' => 'c'), array('value' => 'd'))),
    ),
  );

Bug:
On changing the field to either C or D, 3 red stars appear.

Remarks:
- Firebug does not pick up the loading of states.js (probably because it is loaded as a by result of processing the result of the ajax call), so I could not debug it, other than using console.log.
- On opening the field formatter settings form on the "manage display" screen for the field at hand, I can see that the same event is bound 4 times:
Added logging in states.js

  initializeDependee: function (selector, dependeeStates) {
        ..
        // Monitor state changes of the specified state for this dependee.
        console.log("binding state:" + state + " on " + selector);
        $(selector).bind('state:' + state, $.proxy(function (e) {
          console.log("event handler for state:" + state + " on " + selector);
          this.update(selector, state, e.value);
        }, this));

        // Make sure the event we just bound ourselves to is actually fired.
        new states.Trigger({ selector: selector, state: state });
      }
    }
  },

- console log after opening formatter settings form and after selecting option c:

8 lines of:
binding state:value on :input[name='fields[field_book_now][settings_edit_form][settings][setting1]']

8 lines of:
event handler for state:value on :input[name='fields[field_book_now][settings_edit_form][settings][setting1]']
8 lines of:
binding state:value on :input[name='fields[field_book_now][settings_edit_form][settings][setting1]']

- Looking at the code in initializeDependee:

  initializeDependee: function (selector, dependeeStates) {
    ...
    for (var i in dependeeStates) {
      if (dependeeStates.hasOwnProperty(i)) {
        state = dependeeStates[i];
        // Make sure we're not initializing this selector/state combination twice.
        if ($.inArray(state, dependeeStates) === -1) {
          continue;
        }

$.inArray(state, dependeeStates) will always equals i, so this code, introduced by #735528: FAPI #states: Fix conditionals to allow OR and XOR constructions, tries to achieve something in the wrong way.

However, looking a this code I have no idea what it should be. So I would like to ask those who wrote and reviewed this code to chime in and have a look at it as well.

Comments

fietserwin’s picture

Issue tags: +Regression

If anybody feels that this regression should block 7.15, please add the tag "7.15 release blocker" as well.

nod_’s picture

Version: 7.14 » 8.x-dev
Issue tags: +Needs backport to D7

Well #states is the same in D8 so this needs to be fixed there first.

nod_’s picture

fietserwin’s picture

It looks very much the same. But even, if the issues are the same, or if we decide to merge them, my remark about the code that will never reach the continue statement still holds.

I applied the patch from the other issue to my D7 installation, but that did not solve my problem:

  • Using once: My required marker is there once or not (depending on the #required property as is set on the server) but does not dynamically react to changes.
  • Not using once: The required marker appears either 3 times or not but does react correctly to changes.

I'll see if I can create a simple (manual) test case for both issues and for both D7 and D8.

nod_’s picture

Ohh that would be very, very helpful fietserwin.

fietserwin’s picture