Summary
Errors set by constraints on custom field types appear next to every single property by default.
We can use the ::errorElement()
method on the widget to place errors that come from the ::getConstraints()
method of the field item.
However, errors that come from ::getConstraints()
in a custom field item list will not go through ::errorElement()
. How can we reasonably place them?
Details
My original problem ist very complicated. I've drastically simplified it to show only what's essential. We start with a very simple custom field type with 2 number properties.
class YearRangeType extends FieldItemBase {
public static function propertyDefinitions($field_definition) {
$properties['start'] = DataDefinition::create('integer');
$properties['end'] = DataDefinition::create('integer');
return $properties;
}
public static function schema($field_definition) {
$schema = ['columns' => [
'start' => ['type' => 'int',],
'end' => ['type' => 'int',],
],];
return $schema;
}
public function isEmpty() {
$start = $this->get('start')->getValue();
$end = $this->get('end')->getValue();
return !($start || $end);
}
}
We define a custom FieldItemList
for it that adds a simple validation: checking if at least 2 items are present.
class YearRangeItemList extends FieldItemList {
public function getConstraints() {
$constraints = parent::getConstraints();
$constraints[] = $this->getTypedDataManager()
->getValidationConstraintManager()
->create('Count', [
'min' => 2
]);
return $constraints;
}
}
When I try to save only one item, the field will look like this:
If the errors would result from YearRangeType::getConstraints(), we could use the
errorElement()` method of the widget to place them.
However, the Drupal core class WidgetBase
does deliberately not pass errors set by the item list to errorElement()
, see these lines in the Drupal core code (version 8.8.1).
How else should we place them?