Creating a custom field widget

Field widgets provide the form interface for editing a field. These integrate with the Form API to define how a field can be edited and the way in which the data can be formatted before it is saved. Field widgets are chosen and customized through the form display interface.

In this recipe, we will create a widget for the field created in the Creating a custom field type recipe in this chapter. The field widget will provide two text fields for entering the first and last name items.

Getting ready

Create a new module such as the one existing in the first recipe. We will refer to the module as mymodule throughout the recipe. Use your module's appropriate name.

How to do it…

  1. We need to create the src/Plugin/Field/FieldWidget directory in the module's base location. The Field module discovers field widgets in the PluginFieldFieldWidget namespace.
  2. Create a RealNameDefaultWidget.php file in the newly created directory so that we can define the RealNameDefaultWidget class. This will provide a custom form element to edit the first and last name values of our field:
    How to do it…
  3. The RealNameDefaultWidget class will extend the DrupalCoreFieldWidgetBase class:
    <?php
    
    /**
     * @file
     * Contains DrupalmymodulePluginFieldFieldWidgetRealNameDefaultWidget
     */
    
    namespace DrupalmymodulePluginFieldFieldWidget;
    
    use DrupalCoreFieldWidgetBase;
    
    class RealNameDefaultWidget extends WidgetBase {
    
    }
  4. Field widgets are like annotated plugins. Annotated plugins use documentation blocks to provide details of the plugin. We will provide the field widget's identifier, label, and supported field types:
    <?php
    
    /**
     * @file
     * Contains DrupalmymodulePluginFieldFieldWidgetRealNameDefaultWidget
     */
    
    namespace DrupalmymodulePluginFieldFieldWidget;
    
    use DrupalCoreFieldWidgetBase;
    use DrupalCoreFieldFieldItemListInterface;
    use DrupalCoreFormFormStateInterface;
    
    /**
     * Plugin implementation of the 'realname_default' widget.
     *
     * @FieldWidget(
     *   id = "realname_default",
     *   label = @Translation("Real name"),
     *   field_types = {
     *     "realname"
     *   }
     * )
     */
    class RealNameDefaultWidget extends WidgetBase {
    
    }

    The @FieldWidget tells Drupal that this is a field widget plugin. It defines id to represent the machine name, the human-readable name as label, and the field types that the widget interacts with.

  5. We need to implement the formElement method to satisfy the remaining interface methods after extending DrupalCoreFieldWidgetBase:
      /**
       * {@inheritdoc}
       */
      public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
        $element['first_name'] = array(
          '#type' => 'textfield',
          '#title' => t('First name'),
          '#default_value' => '',
          '#size' => 25,
          '#required' => $element['#required'],
        );
        $element['last_name'] = array(
          '#type' => 'textfield',
          '#title' => t('Last name'),
          '#default_value' => '',
          '#size' => 25,
          '#required' => $element['#required'],
        );
        return $element;
      }

    The formElement method returns a Form API array that represents the widget to be set, and edits the field data.

  6. Next, we need to modify our original RealName field type plugin class in order to use the default widget that we created. Update the default_widget annotation property as realname_default:
    /**
     * Plugin implementation of the 'realname' field type.
     *
     * @FieldType(
     *   id = "realname",
     *   label = @Translation("Real name"),
     *   description = @Translation("This field stores a first and last name."),
     *   category = @Translation("General"),
     *   default_widget = "realname_default",
     *   default_formatter = "string"
     * )
     */
    class RealName extends FieldItemBase {
  7. Rebuild Drupal's cache so that the plugin system can discover the new field widget.
  8. Add a Real name field and use the new Real name widget. For example, add it to a Comment type:
    How to do it…

How it works...

Drupal core defines a plugin.manager.field.widget service. By default, this is handled through the DrupalCoreFieldFieldWidgetPluginManager class. This plugin manager defines the field widget plugins that should be in the Plugin/Field/FieldWidget namespace, and all the classes in this namespace will be loaded and assumed to be field widget plugins.

The manager's definition also sets DrupalCoreFieldFieldWidgetInterface as the expected interface that all the field widget plugins will implement. This is why most field types extend DrupalCoreFieldWidgetBase to meet these method requirements.

As field widgets are annotated plugins, the manager provides DrupalCoreFieldAnnotationFieldWidget as the class that fulfills the annotation definition.

The entity form display system uses the plugin.manager.field.widget service to load field definitions and add the field's element, returned from the formElement method, to the entity form.

There's more

Field widget settings and summary

The DrupalCoreFieldWidgetInterface interface defines three methods that can be overridden to provide a settings form and a summary of the current settings:

  • defaultSettings: This returns an array of the setting keys and default values
  • settingsForm: This returns a Form API array that is used for the settings form
  • settingsSummary: This allows an array of strings to be returned and displayed on the manage display form for the field

Widget settings can be used to alter the form presented to the user. A setting can be created that allows the field element to be limited to only enter the first or last name with one text field.

See also

  • The Creating a custom plugin type recipe of this chapter
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset