Change record status: 
Project: 
Introduced in branch: 
11.x
Introduced in version: 
11.3.0
Description: 

A new object-oriented API has been added for working with form and render and widgets can now written with fully object oriented code without writing any arrays, without #.

Before:

  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element['value'] = $element + [
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->value ?? NULL,
      '#size' => $this->getSetting('size'),
      '#placeholder' => $this->getSetting('placeholder'),
      '#maxlength' => $this->getFieldSetting('max_length'),
      '#attributes' => ['class' => ['js-text-full', 'text-full']],
    ];

    return $element;
  }

After:

  public function singleElementObject(FieldItemListInterface $items, $delta, Widget $widget, ElementInterface $form, FormStateInterface $form_state): ElementInterface {
    $value = $widget->createChild('value', Textfield::class, copyProperties: TRUE);
    $value->default_value = $items[$delta]->value ?? NULL;
    $value->size = $this->getSetting('size');
    $value->placeholder = $this->getSetting('placeholder');
    $value->maxlength = $this->getFieldSetting('max_length');
    $value->attributes = ['class' => ['js-text-full', 'text-full']];
    return $widget;
  }

Note this does not call parent::singleElementObject() and that's correct. WidgetBase::singleElementObject provides backwards compatibility by calling $this->formElement() and wrapping it for the modern OOP elements API, there's no need to call it once the conversion above has been done.

Impacts: 
Module developers