Options module uses '_none' as a special value

Created on 16 May 2012, over 13 years ago
Updated 10 February 2023, over 2 years ago

A user of clientside_validation reported this bug ( #1585554: Validating lists (select-fields) not working correctly โ†’ ), it is caused by the fact that the options.module uses the following: $options = array('_none' => $label).

First problem is that the outputted HTML contains <option value="_none"> and this means the select element has a value.
Second (unrelated) problem is that we allow people to enter "_none|oops" as an allowed value, but it will never be outputted unless a default value is selected.

I found #735426: Fields with select widget: first option is selected by default even if no 'default value' set for the field โ†’ where this was introduced, so I would like to change the use of '_none' to NULL

๐Ÿ› Bug report
Status

Needs work

Version

10.1 โœจ

Component
Fieldย  โ†’

Last updated 7 days ago

Created by

๐Ÿ‡ง๐Ÿ‡ชBelgium attiks

Live updates comments and jobs are added and updated live.
  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

  • Needs backport to D7

    After being applied to the 8.x branch, it should be considered for backport to the 7.x branch. Note: This tag should generally remain even after the backport has been written, approved, and committed.

  • Needs change record

    A change record needs to be drafted before an issue is committed. Note: Change records used to be called change notifications.

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.

  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand john pitcairn
  • Status changed to Needs review over 2 years ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia arunkumark Coimbatore

    The patch has been rerolled for Drupal 10.1.x

  • Status changed to Needs work over 2 years ago
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada joseph.olstad

    Patch 84 still applies cleanly to the HEAD of 9.5.x, 10.0.x and 10.1.x, I just checked vs the latest in each branch.

    Patch 84 passes.

    Patch 85 and 87 were not needed and were incorrectly rolled and fail testing.

    https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupa... โ†’

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom longwave UK

    We still need to address the backward compatibility concerns from #66 onwards: we need a way to allow keep '_none' for existing sites that depend on it, while allowing '' for sites that want to use that instead.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada joseph.olstad

    patch 84 no longer applies to 10.0.x, will need a new patch for 10.0.10

  • last update about 2 years ago
    Custom Commands Failed
  • last update about 2 years ago
    28,519 pass, 2 fail
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Environment: PHP 8.1 & MariaDB 10.3.22
    34:36
    30:39
    Running
  • last update about 2 years ago
    28,519 pass, 2 fail
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia sumithra ramalingam

    Thank you @joseph.olstad
    Patch #93 working clearly with D10.1.4 version.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany luenemann Sรผdbaden, Germany

    Fixed link to project page.

  • last update over 1 year ago
    Patch Failed to Apply
  • last update over 1 year ago
    25,834 pass, 1,819 fail
  • ๐Ÿ‡ฆ๐Ÿ‡ทArgentina darktek

    New 11.2.3 version was released today and patch #93 ๐Ÿ› Options module uses '_none' as a special value Needs work is not working anymore.

    I'm sharing this new patch: https://www.drupal.org/files/issues/2025-08-07/1585930-96.patch โ†’

  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ

    @darktek some changes do not match the 93 patch:

    Why do you replaced "$element['#value'] === ''" by "$element['#value'] == ''" or "if ($value !== '') {" by "if ($value != '') {"?

    interdiff 1585930-93.patch 1585930-96.patch

    diff -u b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php
    --- b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php
    +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php
    @@ -90,7 +90,7 @@
        *   The form state.
        */
       public static function validateElement(array $element, FormStateInterface $form_state) {
    -    if ($element['#required'] && $element['#value'] === '') {
    +    if ($element['#required'] && $element['#value'] == '') {
           if (isset($element['#required_error'])) {
             $form_state->setError($element, $element['#required_error']);
           }
    @@ -144,7 +144,7 @@
     
           // Add an empty option if the widget needs one.
           if ($empty_label = $this->getEmptyLabel()) {
    -        $options = ['' => $empty_label] + $options;
    +        $options = ['_none' => $empty_label] + $options;
           }
     
           $module_handler = \Drupal::moduleHandler();
    diff -u b/core/modules/options/tests/src/Functional/OptionsSelectDynamicValuesTest.php b/core/modules/options/tests/src/Functional/OptionsSelectDynamicValuesTest.php
    --- b/core/modules/options/tests/src/Functional/OptionsSelectDynamicValuesTest.php
    +++ b/core/modules/options/tests/src/Functional/OptionsSelectDynamicValuesTest.php
    @@ -36,7 +36,7 @@
         $this->assertCount(count($this->test) + 1, $options);
         foreach ($options as $option) {
           $value = $option->getValue();
    -      if ($value !== '') {
    +      if ($value != '') {
             $this->assertContains($value, $this->test);
           }
         }
    diff -u b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php
    --- b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php
    +++ b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php
    @@ -613,7 +613,7 @@
     
         // Display form: check that empty '' option is present and has label.
         $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
    -    $this->assertNotEmpty($this->xpath('//div[@id=:id]//input[@value=:value]', [':id' => 'edit-card-1', ':value' => '']), 'A test radio button has a "None" choice.');
    +       $this->assertNotEmpty($this->xpath('//div[@id=:id]//input[@value=:value]', [':id' => 'edit-card-1', ':value' => '']), 'A test radio button has a "None" choice.');
     
         // Change it to the select widget.
         $display_repository->getFormDisplay('entity_test', 'entity_test')
    diff -u b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php
    --- b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php
    +++ b/core/modules/workspaces/tests/src/Functional/WorkspaceTestUtilities.php
    @@ -52,12 +52,12 @@
        * @param string $id
        *   The ID of the workspace to create.
        * @param string $parent
    -   *   (optional) The ID of the parent workspace. Defaults to ''.
    +   *   (optional) The ID of the parent workspace. Defaults to '_none'.
        *
        * @return \Drupal\workspaces\WorkspaceInterface
        *   The workspace that was just created.
        */
    -  protected function createWorkspaceThroughUi($label, $id, $parent = '') {
    +  protected function createWorkspaceThroughUi($label, $id, $parent = '_none') {
         $this->drupalGet('/admin/config/workflow/workspaces/add');
         $this->submitForm([
           'id' => $id,
    @@ -94,12 +94,12 @@
        * @param string|null $id
        *   The ID of the workspace to create.
        * @param string $parent
    -   *   (optional) The ID of the parent workspace. Defaults to '_none'.
    +   *   (optional) The ID of the parent workspace. Defaults to ''.
        *
        * @return \Drupal\workspaces\WorkspaceInterface
        *   The workspace that was just created.
        */
    -  protected function createWorkspaceThroughUi(?string $label = NULL, ?string $id = NULL, string $parent = '_none') {
    +  protected function createWorkspaceThroughUi(?string $label = NULL, ?string $id = NULL, string $parent = '') {
         $id ??= $this->randomMachineName();
         $label ??= $this->randomString();
    
  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ

    We will open a MR to track the changes properly

  • Pipeline finished with Failed
    29 days ago
    Total: 147s
    #576261
  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ
  • Pipeline finished with Failed
    29 days ago
    Total: 482s
    #576268
  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ

    Failed PHPUnit:

        Options Widgets (Drupal\Tests\options\Functional\OptionsWidgets)
         โœ” Radio buttons
         โœ” Check boxes
         โœ” Select list single
         โœ˜ Select list required error attribute
           โ”
           โ”œ Behat\Mink\Exception\ElementNotFoundException: Option with id|name|label|value "_none" not found.
           โ”‚
           โ”‚ /builds/issue/drupal-1585930/core/tests/Drupal/Tests/WebAssert.php:241
           โ”‚ /builds/issue/drupal-1585930/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php:406
           โ”ด
         โœ” Select list multiple
         โœ” Select list float
         โœ” Empty value
         โœ˜ Options list alter
           โ”
           โ”œ Behat\Mink\Exception\ElementNotFoundException: Element matching xpath "//select[@id="edit-card-1"]//option[@value="_none" and text()="- None -"]" not found.
           โ”‚
           โ”‚ /builds/issue/drupal-1585930/vendor/behat/mink/src/WebAssert.php:465
           โ”‚ /builds/issue/drupal-1585930/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php:689
    
  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ
  • Pipeline finished with Failed
    29 days ago
    Total: 508s
    #576288
  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ

    Failing:

        Options Widgets (Drupal\Tests\options\Functional\OptionsWidgets)
         โœ” Radio buttons
         โœ” Check boxes
         โœ” Select list single
         โœ” Select list required error attribute
         โœ” Select list multiple
         โœ” Select list float
         โœ” Empty value
         โœ˜ Options list alter
           โ”
           โ”œ Behat\Mink\Exception\ElementNotFoundException: Element matching xpath "//select[@id="edit-card-4"]//option[@value="" and text()="- Select something -"]" not found.
           โ”‚
           โ”‚ /builds/issue/drupal-1585930/vendor/behat/mink/src/WebAssert.php:465
           โ”‚ /builds/issue/drupal-1585930/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php:691
    
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands idebr

    To minimize the BC break, I suggest we map the _none option to the Select #empty_option and set #empty_value to an empty string in a process callback.

    This implementation allows existing options to remain unchanged; only client side logic is impacted (eg. JavaScript)

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands idebr

    idebr โ†’ changed the visibility of the branch 1585930-options-module-uses to hidden.

  • Pipeline finished with Failed
    8 days ago
    Total: 549s
    #593649
  • Pipeline finished with Success
    8 days ago
    Total: 392s
    #593798
  • Pipeline finished with Success
    8 days ago
    Total: 430s
    #593811
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands idebr

    Based on the issue summary, comments and related issues the immediate problem is limited to single select elements and client side validation. If I missed something, let me know and I can update the issue accordingly

    Refactoring the _none value itself is being worked on in ๐Ÿ“Œ Convert '_none' option to a constant and deprecate form_select_options() Needs work

  • Pipeline finished with Success
    8 days ago
    #593854
Production build 0.71.5 2024