diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index 39daf849aa..53afc4e106 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -111,15 +111,6 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
$elements = $this->formMultipleElements($items, $form, $form_state);
}
- // Allow modules to alter the field multi-value widget form element.
- // This hook can also be used for single-value fields.
- $context = [
- 'form' => $form,
- 'widget' => $this,
- 'items' => $items,
- 'default' => $this->isDefaultValueWidget($form_state),
- ];
-
// Populate the 'array_parents' information in $form_state->get('field')
// after the form is built, so that we catch changes in the form structure
// performed in alter() hooks.
@@ -267,6 +258,31 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
'effect' => 'fade',
],
];
+
+ // By default, the limit quantity is defined by quantity of items.
+ $optionsAvailable = $items->count();
+ $emptyValues = $items->count() - count(array_filter($items->getValue()));
+ if (!$items->getEntity()->isNew()) {
+ // None options available when editing a field to avoid empty input field.
+ $optionsAvailable = 0;
+ $userInput = $form_state->getUserInput();
+ $isAddingMore = isset($userInput["_triggering_element_name"])
+ && $userInput["_triggering_element_name"] == $field_name . '_add_more';
+ // On add more action only one option must appear to the user.
+ if ($isAddingMore) {
+ $optionsAvailable = 1;
+ }
+ }
+ elseif ($items->count() > $emptyValues) {
+ $optionsAvailable = 0;
+ }
+
+ // Remove leftover option.
+ if ($emptyValues > $optionsAvailable) {
+ unset($elements[$max]);
+ $items->removeItem($max);
+ $elements["#max_delta"] = $items->count() - 1;
+ }
}
}
diff --git a/core/modules/field/tests/src/Functional/FormTest.php b/core/modules/field/tests/src/Functional/FormTest.php
index 3fbe668953..807afcf14b 100644
--- a/core/modules/field/tests/src/Functional/FormTest.php
+++ b/core/modules/field/tests/src/Functional/FormTest.php
@@ -686,7 +686,8 @@ public function testLabelOnMultiValueFields() {
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->pageTextContains('A field with multiple values');
// Test if labels were XSS filtered.
- $this->assertSession()->assertEscaped("");
+ $this->assertSession()->pageTextContains("alert('a configurable field');");
+ $this->assertSession()->pageTextNotContains("");
}
/**
diff --git a/core/modules/field/tests/src/Functional/NestedFormTest.php b/core/modules/field/tests/src/Functional/NestedFormTest.php
index 4bd2f97c6b..5b67b003ab 100644
--- a/core/modules/field/tests/src/Functional/NestedFormTest.php
+++ b/core/modules/field/tests/src/Functional/NestedFormTest.php
@@ -124,6 +124,8 @@ public function testNestedFieldForm() {
$this->assertSession()->fieldValueEquals('entity_2[field_unlimited][0][value]', 11);
// Submit the form and check that the entities are updated accordingly.
+ $this->submitForm([], 'field_unlimited_add_more');
+ $this->submitForm([], 'entity_2_field_unlimited_add_more');
$edit = [
'field_single[0][value]' => 1,
'field_unlimited[0][value]' => 2,
@@ -177,6 +179,7 @@ public function testNestedFieldForm() {
// 'Add more' button in the first entity:
$this->drupalGet('test-entity/nested/1/2');
$this->submitForm([], 'field_unlimited_add_more');
+ $this->submitForm([], 'field_unlimited_add_more');
$this->assertSession()->fieldValueEquals('field_unlimited[0][value]', 3);
$this->assertSession()->fieldValueEquals('field_unlimited[1][value]', 2);
$this->assertSession()->fieldValueEquals('field_unlimited[2][value]', '');
@@ -187,6 +190,7 @@ public function testNestedFieldForm() {
'entity_2[field_unlimited][1][value]' => 14,
'entity_2[field_unlimited][2][value]' => 15,
];
+ $this->submitForm([], 'entity_2_field_unlimited_add_more');
$this->submitForm($edit, 'entity_2_field_unlimited_add_more');
$this->assertSession()->fieldValueEquals('entity_2[field_unlimited][0][value]', 13);
$this->assertSession()->fieldValueEquals('entity_2[field_unlimited][1][value]', 14);