Form API #states property/states should use .once() to apply its rules (Can cause failures with BigPipe and possibly other situations)

Created on 10 March 2023, almost 2 years ago
Updated 2 September 2024, 4 months ago

Problem/Motivation

With 🐛 The attachBehaviors() for document is only called after Big Pipe chunks are processed Fixed 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

🐛 Bug report
Status

Fixed

Version

11.0 🔥

Component
Javascript 

Last updated 1 day ago

Created by

🇱🇹Lithuania Evaldas Užkuras Kaunas, LT

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024