Avoid storing empty third party settings when a form is added through hook_field_widget_third_party_settings_form

Created on 9 March 2023, almost 2 years ago

Problem/Motivation

Adding third party setting to a widget and then saving that widget with no modification stores the empty data in the configuration adding a dependency on the module that provides the thrird party setting.

Steps to reproduce

Place the following code in a module called `change_labels`:

function change_labels_field_widget_third_party_settings_form(\Drupal\Core\Field\WidgetInterface $plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, array $form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $element = [];
    $element['field_label_overwrite'] = [
      '#type' => 'textfield',
      '#title' => t('Overwrite field label'),
      '#description' => t('Enter &ltnolabel> to remove the label.'),
      '#default_value' => $plugin->getThirdPartySetting('change_labels', 'field_label_overwrite'),
    ];
   return $element;

Enable it and and configure a widget inside a form mode.
You can see the new field. Leave it empty and save the form mode display.
Inspect the configuration to discover an empty string was saved and there is a new dependency on the `change_labels` module.

Proposed resolution

I believe the code that stores the thrird party setting shouldn't save anything that look empty like empty strings, unchecked checkboxes, etc.
Another possible solution is to give the chance to modules to decide when a third party setting is empty so it is not stored.

Remaining tasks

Agree on a solution

User interface changes

None

API changes

None

Data model changes

Modules that were saving empty third party settings and treating it differently that non-existing settings but I think such thing exists and is a bad practice anyway.

Release notes snippet

Empty third party settings for widgets are no longer stored.

Feature request
Status

Active

Version

10.1

Component
Field UI 

Last updated 7 days ago

Created by

🇪🇸Spain rodrigoaguilera Barcelona

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @rodrigoaguilera
  • 🇧🇪Belgium rp7

    +1 for this. My config is riddled with "empty" config like this.

    People looking for a temporary workaround, this one seems to work for me:

    /**
     * Implements hook_field_widget_third_party_settings_form().
     */
    function mymodule_ux_field_widget_third_party_settings_form(WidgetInterface $plugin, FieldDefinitionInterface $field_definition, $form_mode, array $form, FormStateInterface $form_state) {
        $element = [];
    
        // Add a "nested_hide_level" checkbox to the settings form.
        $element['mysetting'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('My setting'),
          '#default_value' => $plugin->getThirdPartySetting('mymodule', 'mysetting'),
          '#required' => FALSE,
          '#element_validate' => ['_mymodule_validate_mysetting'],
        ];
    
        return $element;
    }
    
    /**
     * Validates mysetting.
     */
    function _mymodule_validate_mysetting(&$element, FormStateInterface $form_state, &$complete_form) {
      if (empty($element['#value'])) {
        $form_state->unsetValue(array_slice($element['#parents'], 0, -1));
      }
    }
    
Production build 0.71.5 2024