#StackBounty: #fields Why are values input to a custom field not being saved by the field widget

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 field has more than one property, like an image field or a body field.

  • The module enables cleanly.
  • The field table contains all the properties 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 each property in the default settings pane, properly.
  • When content is created, the field and its properties 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 properties are empty.
In inspecting the field in the database, the instance meta such as bundle, and entity_id are populated, but the property columns are NULL.

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.'));

        $properties['original_filename'] = DataDefinition::create('string')
            ->setLabel(t('Original Filename'))
            ->setDescription(t('The name of the video file that was uploaded to YouTube.'));

        $properties['original_format'] = DataDefinition::create('string')
            ->setLabel(t('Original Format'))
            ->setDescription(t('The video format of the original file that was uploaded to YouTube.'));

        $properties['video_length'] = DataDefinition::create('string')
            ->setLabel(t('Video Length'))
            ->setDescription(t('The duration of the video, in hours:minutes:seconds.'));

        $properties['youtube_url'] = DataDefinition::create('string')
            ->setLabel(t('Video YouTube URL'))
            ->setDescription(t('The YouTube URL at which the video can be referenced.'));

        $properties['poster_image'] = DataDefinition::create('integer')
        ->setLabel(t('Poster Image'))
        ->setDescription(t('The image to be displayed in the video player prior to starting the video.'))
        ->setSetting('file_directory', 'IMAGE_FOLDER')
        ->setSetting('alt_field_required', FALSE)
        ->setSetting('file_extensions', 'png jpg jpeg');

        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,
            ),
            'original_filename' => array(
                'description' => 'The name of the video file that was uploaded to YouTube.',
                'type' => 'varchar',
                'length' => 255,
            ),
            'original_format' => array(
                'description' => 'The video format of the original file uploaded to YouTube.',
                'type' => 'varchar',
                'length' => 255,
            ),
            'video_length' => array(
                'description' => 'The duration of the video, in hours:minutes:seconds.',
                'type' => 'varchar',
                'length' => 8,
            ),
            'youtube_url' => array(
                'description' => 'The URL at which the video can be referenced on YouTube.',
                'type' => 'varchar',
                'length' => 255,
            ),
            'poster_image' => array(
                'description' => 'An image to be displayed in the video player prior to the video starting.',
                'type' => 'int',
                'not null' => false,
                'unsigned' => true,
            ),

        );

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

        return $schema;
    }

And here is the field widget code:
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",
 *   },
 * )
 */
// *   multiple_values = TRUE,

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,
            '#empty_value' => '',
            '#placeholder' => t(''),
            '#size' => 60,
        ];

        $element['video_meta']['original_filename'] = [
            '#type' => 'textfield',
            '#title' => t('Original Filename'),
            '#default_value' => isset($items[$delta]->original_filename) ? $items[$delta]->original_filenamne : NULL,
            '#empty_value' => '',
            '#placeholder' => t(''),
            '#size' => 60,
        ];

        $element['video_meta']['original_format'] = [
            '#type' => 'textfield',
            '#title' => t('Original Format'),
            '#default_value' => isset($items[$delta]->original_format) ? $items[$delta]->original_format : NULL,
            '#empty_value' => '',
            '#placeholder' => t(''),
            '#size' => 20,
        ];

        $element['video_meta']['video_length'] = [
            '#type' => 'textfield',
            '#title' => t('Video Length'),
            '#default_value' => isset($items[$delta]->video_length) ? $items[$delta]->video_length : NULL,
            '#empty_value' => '',
            '#placeholder' => t('h:mm:ss'),
            '#size' => 8,
        ];

        $element['video_meta']['youtube_url'] = [
            '#type' => 'url',
            '#title' => t('YouTube URL'),
            '#default_value' => isset($items[$delta]->youtube_url) ? $items[$delta]->youtube_url : NULL,
            '#empty_value' => '',
            '#placeholder' => t(''),
            '#size' => 60,
        ];

        $element['video_meta']['poster_image'] = [
            '#type' => 'managed_file',
            '#title' => t('Poster Image'),
            '#description' => t('The image to be displayed in the video player prior to video playback.'),
            //'#default_value' => $this->get('image'),
            '#upload_location' => 'public://images/',
        ];

        return $element;
    }
}

and 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    |       |
| field_svideo_original_filename | varchar(255)     | YES  |     | NULL    |       |
| field_svideo_original_format   | varchar(255)     | YES  |     | NULL    |       |
| field_svideo_video_length      | varchar(8)       | YES  |     | NULL    |       |
| field_svideo_youtube_url       | varchar(255)     | YES  |     | NULL    |       |
| field_svideo_poster_image      | int(10) unsigned | YES  |     | NULL    |       |
+--------------------------------+------------------+------+-----+---------+-------+


Get this bounty!!!

Leave a Reply

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