- Issue created by @goz
I try to add to the settings form of a field group a complex element, but i cannot change values.
I create a field group details icon which is based on details field group, but on which i can add and configure an icon to display with label.
I use icon_autocomplete widget, which return values composed by an IconDefinition object and settings as array.
I don't want to store all the IconDefinition in my schema, but only pack_id and icon_id.
Unfortunately, i cannot edit those values before they are casted and validated to be stored. This throw an exception.
Drupal\Core\Config\UnsupportedDataTypeConfigException: Invalid data type for config element core.entity_form_display.node.page.default:third_party_settings.field_group.group_test.format_settings.icon.icon in Drupal\Core\Config\StorableConfigBase->validateValue() (line 201 of core/lib/Drupal/Core/Config/StorableConfigBase.php).
Drupal\Core\Config\StorableConfigBase->validateValue('third_party_settings.field_group.group_test.format_settings.icon', Array) (Line: 197)
Drupal\Core\Config\StorableConfigBase->validateValue('third_party_settings.field_group.group_test.format_settings', Array) (Line: 230)
Drupal\Core\Config\StorableConfigBase->castValue('third_party_settings.field_group.group_test.format_settings', Array) (Line: 258)
Drupal\Core\Config\StorableConfigBase->castValue('third_party_settings.field_group.group_test', Array) (Line: 258)
Drupal\Core\Config\StorableConfigBase->castValue('third_party_settings.field_group', Array) (Line: 258)
Drupal\Core\Config\StorableConfigBase->castValue('third_party_settings', Array) (Line: 258)
Drupal\Core\Config\StorableConfigBase->castValue(NULL, Array) (Line: 211)
Drupal\Core\Config\Config->save() (Line: 260)
Drupal\Core\Config\Entity\ConfigEntityStorage->doSave('node.page.default', Object) (Line: 486)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 239)
Drupal\Core\Config\Entity\ConfigEntityStorage->save(Object) (Line: 354)
Drupal\Core\Entity\EntityBase->save() (Line: 617)
Drupal\Core\Config\Entity\ConfigEntityBase->save() (Line: 914)
field_group_group_save(Object, Object) (Line: 525)
field_group_field_overview_submit(Array, Object)
call_user_func_array('field_group_field_overview_submit', Array) (Line: 105)
Add in the settings form of a new field group :
<?php
namespace Drupal\field_group_icon\Plugin\field_group\FieldGroupFormatter;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Theme\Icon\IconDefinitionInterface;
use Drupal\field_group\FieldGroupFormatterBase;
use Drupal\field_group\Plugin\field_group\FieldGroupFormatter\Details;
/**
* Plugin implementation of the 'details_icon' formatter.
*
* @FieldGroupFormatter(
* id = "details_icon",
* label = @Translation("Details with icon"),
* description = @Translation("Add a details element with icon"),
* supported_contexts = {
* "form",
* "view"
* }
* )
*/
class DetailsIcon extends Details {
/**
* {@inheritdoc}
*/
public function settingsForm() {
$form = parent::settingsForm();
$icon = NULL;
if ($this->getSetting('icon') && isset($this->getSetting('icon')['icon'])) {
$icon = $this->getSetting('icon')['icon'];
if ($icon instanceof IconDefinitionInterface) {
$icon = [
'pack_id' => $icon->getPackId(),
'icon_id' => $icon->getIconId(),
];
}
}
$form['icon'] = [
'#title' => $this->t('Icon'),
'#type' => 'icon_autocomplete',
'#default_value' => $icon ? "{$icon['pack_id']}:{$icon['icon_id']}" : NULL,
'#default_settings' => $this->getSetting('icon') ? $this->getSetting('icon')['settings'] : NULL,
];
$form['icon_position'] = [
'#title' => $this->t('Icon position'),
'#type' => 'select',
'#options' => [
'left' => $this->t('Left'),
'right' => $this->t('Right'),
'top' => $this->t('Top'),
'bottom' => $this->t('Bottom'),
],
'#required' => TRUE,
'#default_value' => $this->getSetting('icon_position') ?? 'left',
];
$form['icon_size'] = [
'#title' => $this->t('Icon size'),
'#type' => 'css_size',
'#default_value' => $this->getSetting('icon_size') ?? ['number' => 1, 'unit' => 'em'],
];
$form['#submit'][] = [[get_class($this), 'submitSettingsForm']];
return $form;
}
public function massageFormValues(array &$values) {
if (NULL === $values['icon']) {
return;
}
/** @var \Drupal\Core\Theme\Icon\IconDefinitionInterface $iconDefinition */
$iconDefinition = $values['icon']['icon'];
$values['icon'] = [
'icon' => [
'pack_id' => $iconDefinition->getPackId(),
'icon_id' => $iconDefinition->getIconId(),
],
'settings' => $values['icon']['settings'],
];
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
if ($this->getSetting('icon_position')) {
$summary[] = $this->t('Icon position: @position', ['@position' => $this->getSetting('icon_position')]);
}
if ($this->getSetting('icon_size')) {
$icon_size = $this->getSetting('icon_size');
$summary[] = $this->t('Icon size: @number @unit', ['@number' => $icon_size['number'], '@unit' => $icon_size['unit']]);
}
return $summary;
}
}
and here is my schema for this new field group
field_group_icon.field_group_formatter_plugin.details_icon:
type: field_group.field_group_formatter_plugin.details
label: 'Mapping for the details formatter settings'
mapping:
icon:
mapping:
icon:
type: mapping
label: 'Icon settings'
mapping:
pack_id:
type: string
icon_id:
type: string
settings:
type: sequence
label: 'Icon extractor settings'
sequence:
type: ui_icons.icon_pack_options.[%key]
icon_position:
type: string
label: 'Position of the icon.'
icon_size:
type: mapping
label: 'Size of the icon.'
mapping:
number:
type: float
label: 'The value number of the size.'
unit:
type: string
label: 'The unit of the size.'
Like Form widget do, add a massageFormValues() methods so plugin can alter values to make them storable.
In field_ui.inc, update field_group_formatter_settings_update to allow massage form values.
function field_group_formatter_settings_update(&$group, array $settings) {
// For format changes we load the defaults.
if (empty($settings['settings_edit_form']['settings'])) {
$group->format_settings = Drupal::service('plugin.manager.field_group.formatters')->getDefaultSettings($group->format_type, $group->context);
}
else {
$group->format_type = $settings['format']['type'];
$group->label = $settings['settings_edit_form']['settings']['label'];
$group->format_settings = $settings['settings_edit_form']['settings'];
}
$manager = Drupal::service('plugin.manager.field_group.formatters');
$plugin = $manager->getInstance([
'format_type' => $group->format_type,
'configuration' => [
'label' => $group->label,
],
'group' => $group,
]);
$plugin->massageSettingsFormValues($group->format_settings);
}
So, in my case, i'm able to transform submitted settings by settings defined in my plugin schema :
public function massageSettingsFormValues(array &$values) {
if (NULL === $values['icon']) {
return;
}
/** @var \Drupal\Core\Theme\Icon\IconDefinitionInterface $iconDefinition */
$iconDefinition = $values['icon']['icon'];
$values['icon'] = [
'icon' => [
'pack_id' => $iconDefinition->getPackId(),
'icon_id' => $iconDefinition->getIconId(),
],
'settings' => $values['icon']['settings'],
];
}
Active
4.0
Code