In the previous topic, we created a custom Field Type, which defined how data is stored and structured. Now we move to the next layer of the field system: Field Widgets.
If a field type defines the data model, a field widget defines how users input that data.
Widgets are responsible for:
- Rendering form elements
- Handling input structure
- Providing configuration options
- Integrating with validation
This topic continues the learning-by-building approach using the same weeklydrupal_demo module and the rating field type we created earlier.
By the end of this article, you will understand:
- What a field widget is
- How widgets connect to field types
- How to create a custom widget plugin
- How Drupal builds widget form elements
- When to create a custom widget
1. What Is a Field Widget
A field widget controls how a field appears on entity edit forms.
For example:
- A text field may use a text input or textarea
- A boolean field may use a checkbox
- An entity reference field may use autocomplete
The same field type can have multiple widgets.
In simple terms:
Field type = how data is stored
Field widget = how data is entered
2. Where Field Widgets Live
Widgets are plugin classes located in:
src/Plugin/Field/FieldWidget
Drupal discovers them using annotations.
3. Creating a Widget for the Rating Field
We will create a custom widget for our rating field type.
File path
weeklydrupal_demo/src/Plugin/Field/FieldWidget/RatingWidget.php
Code
<?php
namespace Drupal\weeklydrupal_demo\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'rating_widget' widget.
*
* @FieldWidget(
* id = "rating_widget",
* label = @Translation("Rating Select"),
* field_types = {
* "rating"
* }
* )
*/
class RatingWidget extends WidgetBase {
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$value = isset($items[$delta]->value) ? $items[$delta]->value : NULL;
$element['value'] = [
'#type' => 'select',
'#title' => $this->t('Rating'),
'#options' => [
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
],
'#default_value' => $value,
];
return $element;
}
}
4. Understanding the Annotation
@FieldWidget(
id = "rating_widget",
label = @Translation("Rating Select"),
field_types = { "rating" }
)
Explanation:
id– Machine name of the widgetlabel– Displayed in field UIfield_types– Which field types this widget supports
This connects the widget to the rating field type.
5. The formElement() Method
public function formElement(...)
This method:
- Builds the form element
- Receives the current field values
- Returns a render array
Drupal automatically integrates this into the entity edit form.
6. Understanding $items and $delta
$itemscontains field values$deltarepresents the index when fields allow multiple values
For multi-value fields, Drupal calls formElement() once per item.
7. How Drupal Uses the Widget
When editing an entity:
- Drupal loads field definitions
- Finds the selected widget
- Calls
formElement() - Merges returned render array into the form
The widget does not save data directly. Drupal handles storage.
8. Widget Configuration
Widgets can provide configuration settings.
Example:
public static function defaultSettings() {
return [
'max_rating' => 5,
] + parent::defaultSettings();
}
You can then use this setting inside formElement().
This allows widgets to be flexible and reusable.
9. When to Create a Custom Widget
Create a custom widget when:
- Default widgets do not match UX requirements
- You need specialized input structure
- You need controlled input options
- Validation depends on structured input
Do not create a custom widget just for styling. That belongs in themes.
10. Common Mistakes to Avoid
- Mixing storage logic inside the widget
- Hardcoding values that should be configurable
- Ignoring multi-value behavior
- Not returning the correct render array structure
Widgets should focus only on input.
11. Learning by Building: weeklydrupal_demo
Our module now includes:
- Custom field type
- Custom field widget
- Typed data definitions
- Schema integration
Next we will complete the field system by building a Field Formatter.
12. Why Field Widgets Matter
Understanding field widgets helps you:
- Control editorial experience
- Build structured input systems
- Improve usability without breaking storage
- Separate data model from UI
This separation is central to Drupal architecture.