#StackBounty: #fields Why won't custom field property values save if they are in a fieldset?

Bounty: 50

I’m creating a custom field for use with a bundle. I’m mentioning ‘bundle’ explicitly because the details of creating the field for use with an entity are slightly different.

  • The module enables cleanly.
  • The field table contains the property as defined in the field schema.
  • The field name appears in the Add Field dialog.
  • The field is added to a bundle cleanly, and its settings form contains the property in the default settings pane, properly.
  • When content is created, the field and its property appear in the node edit form correctly.
  • The node saves without throwing any errors.

When the node is saved and then re-edited, the field property is empty.
In inspecting the field in the database, the instance meta such as bundle, and entity_id are populated, but the property column is NULL.

If the fieldset is removed, the value is saved as expected.

Here is the field code:
web/modules/custom/test_video_widget/src/Plugin/Field/FieldType/TestVideoWidgetField.php

<?php
namespace Drupaltest_video_widgetPluginFieldFieldType;

use DrupalCoreFieldFieldItemBase;
use DrupalCoreFieldFieldStorageDefinitionInterface;
use DrupalCoreTypedDataDataDefinition;

/**
 * @FieldType(
 *   id = "test_video_widget",
 *   module = "test_video_widget",
 *   label = @Translation("Test Video Widget"),
 *   description = @Translation("This field stores video meta information."),
 *   default_widget = "TestVideoWidgetW",
 *   default_formatter = "TestVideoWidgetFormatter",
 * )
 */


class TestVideoWidgetField extends FieldItemBase {
    /**
     * {@inheritdoc}
     */
    public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {

        $properties = [];

        $properties['video_title'] = DataDefinition::create('string')
            ->setLabel(t('Video Title'))
            ->setDescription(t('Optional title to be displayed instead of the node title.'));

        return $properties;
    }

    /**
     * {@inheritdoc}
     */
    public static function schema(FieldStorageDefinitionInterface $field_definition) {
        $columns = array(
            'video_title' => array(
                'description' => 'Optional title to be displayed instead of the node title.',
                'type' => 'varchar',
                'length' => 255,
            ),
        );

        $schema = array(
            'columns' => $columns,
            'indexes' => [],
            //'foreign keys' => array(),
        );

        return $schema;
    }

Here is the field widget code that does NOT work:
web/modules/custom/test_video_widget/src/Plugin/Field/FieldWidget/TestVideoWidgetW.php

<?php
namespace Drupaltest_video_widgetPluginFieldFieldWidget;

use DrupalCoreFieldFieldItemListInterface;
use DrupalCoreFieldWidgetBase;
use DrupalCoreFormFormStateInterface;

/**
 *
 * @FieldWidget(
 *   id = "TestVideoWidgetW",
 *   label = @Translation("Test Video Widget - Widget"),
 *   description = @Translation("Test Video Widget - Widget"),
 *   field_types = {
 *     "test_video_widget",
 *   },
 * )
 */

class TestVideoWidgetW extends WidgetBase {
  /**
   * {@inheritdoc}
   */
    public function formElement(
        FieldItemListInterface $items,
        $delta,
        array $element,
        array &$form,
        FormStateInterface $form_state
    ) {
        $element['video_meta'] = [
            '#type' => 'fieldset',
            '#title' => t('Video Meta'),
        ];

        $element['video_meta']['video_title'] = [
            '#type' => 'textfield',
            '#title' => t('Video Title'),
            '#default_value' => isset($items[$delta]->video_title) ? $items[$delta]->video_title : NULL,
            '#placeholder' => t(''),
            '#size' => 60,
        ];

        return $element;
    }
}

and here is the same method without the fieldset, which DOES work:

    public function formElement(
        FieldItemListInterface $items,
        $delta,
        array $element,
        array &$form,
        FormStateInterface $form_state
    ) {
        $element['video_title'] = [
            '#type' => 'textfield',
            '#title' => t('Video Title'),
            '#default_value' => isset($items[$delta]->video_title) ? $items[$delta]->video_title : NULL,
            '#placeholder' => t(''),
            '#size' => 60,
        ];

        return $element;
    }

also, the resulting field table for the field added to the bundle:

node__field_svideo;
+--------------------------------+------------------+------+-----+---------+-------+
| Field                          | Type             | Null | Key | Default | Extra |
+--------------------------------+------------------+------+-----+---------+-------+
| bundle                         | varchar(128)     | NO   | MUL |         |       |
| deleted                        | tinyint(4)       | NO   | PRI | 0       |       |
| entity_id                      | int(10) unsigned | NO   | PRI | NULL    |       |
| revision_id                    | int(10) unsigned | NO   | MUL | NULL    |       |
| langcode                       | varchar(32)      | NO   | PRI |         |       |
| delta                          | int(10) unsigned | NO   | PRI | NULL    |       |
| field_svideo_video_title       | varchar(255)     | YES  |     | NULL    |       |
+--------------------------------+------------------+------+-----+---------+-------+


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.