Loading core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php +6 −1 Original line number Diff line number Diff line Loading @@ -90,8 +90,13 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen */ public static function validateElement(array $element, FormStateInterface $form_state) { if ($element['#required'] && $element['#value'] == '_none') { if (isset($element['#required_error'])) { $form_state->setError($element, $element['#required_error']); } else { $form_state->setError($element, new TranslatableMarkup('@name field is required.', ['@name' => $element['#title']])); } } // Massage submitted form values. // Drupal\Core\Field\WidgetBase::submit() expects values as Loading core/modules/options/tests/options_test/options_test.module +10 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements callback_allowed_values_function(). Loading Loading @@ -54,3 +55,12 @@ function options_test_dynamic_values_callback(FieldStorageDefinitionInterface $d // We need the values of the entity as keys. return array_combine($values, $values); } /** * Implements hook_form_FORM_ID_alter(). */ function options_test_form_entity_test_entity_test_form_alter(&$form, FormStateInterface $form_state, $form_id) { if (\Drupal::state()->get('options_test.form_alter_enable', FALSE)) { $form['card_1']['widget']['#required_error'] = t('This is custom message for required field.'); } } core/modules/options/tests/src/Functional/OptionsWidgetsTest.php +38 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,44 @@ public function testSelectListSingle() { $this->assertFieldValues($entity_init, 'card_1', []); } /** * Tests the '#required_error' attribute for the select list. */ public function testSelectListRequiredErrorAttribute() { // Enable form alter hook. \Drupal::state()->set('options_test.form_alter_enable', TRUE); // Create an instance of the 'single value' field. $field = FieldConfig::create([ 'field_storage' => $this->card1, 'bundle' => 'entity_test', 'required' => TRUE, ]); $field->save(); \Drupal::service('entity_display.repository') ->getFormDisplay('entity_test', 'entity_test') ->setComponent($this->card1->getName(), [ 'type' => 'options_select', ]) ->save(); // Create an entity. $entity = EntityTest::create([ 'user_id' => 1, 'name' => $this->randomMachineName(), ]); $entity->save(); $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A required field without any value has a "none" option. $option = $this->assertSession()->optionExists('edit-card-1', '_none'); $this->assertSame('- Select a value -', $option->getText()); // Submit form: select invalid 'none' option. $edit = ['card_1' => '_none']; $this->submitForm($edit, 'Save'); $this->assertSession()->responseContains(t('This is custom message for required field.')); } /** * Tests the 'options_select' widget (multiple select). */ Loading Loading
core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php +6 −1 Original line number Diff line number Diff line Loading @@ -90,8 +90,13 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen */ public static function validateElement(array $element, FormStateInterface $form_state) { if ($element['#required'] && $element['#value'] == '_none') { if (isset($element['#required_error'])) { $form_state->setError($element, $element['#required_error']); } else { $form_state->setError($element, new TranslatableMarkup('@name field is required.', ['@name' => $element['#title']])); } } // Massage submitted form values. // Drupal\Core\Field\WidgetBase::submit() expects values as Loading
core/modules/options/tests/options_test/options_test.module +10 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements callback_allowed_values_function(). Loading Loading @@ -54,3 +55,12 @@ function options_test_dynamic_values_callback(FieldStorageDefinitionInterface $d // We need the values of the entity as keys. return array_combine($values, $values); } /** * Implements hook_form_FORM_ID_alter(). */ function options_test_form_entity_test_entity_test_form_alter(&$form, FormStateInterface $form_state, $form_id) { if (\Drupal::state()->get('options_test.form_alter_enable', FALSE)) { $form['card_1']['widget']['#required_error'] = t('This is custom message for required field.'); } }
core/modules/options/tests/src/Functional/OptionsWidgetsTest.php +38 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,44 @@ public function testSelectListSingle() { $this->assertFieldValues($entity_init, 'card_1', []); } /** * Tests the '#required_error' attribute for the select list. */ public function testSelectListRequiredErrorAttribute() { // Enable form alter hook. \Drupal::state()->set('options_test.form_alter_enable', TRUE); // Create an instance of the 'single value' field. $field = FieldConfig::create([ 'field_storage' => $this->card1, 'bundle' => 'entity_test', 'required' => TRUE, ]); $field->save(); \Drupal::service('entity_display.repository') ->getFormDisplay('entity_test', 'entity_test') ->setComponent($this->card1->getName(), [ 'type' => 'options_select', ]) ->save(); // Create an entity. $entity = EntityTest::create([ 'user_id' => 1, 'name' => $this->randomMachineName(), ]); $entity->save(); $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A required field without any value has a "none" option. $option = $this->assertSession()->optionExists('edit-card-1', '_none'); $this->assertSame('- Select a value -', $option->getText()); // Submit form: select invalid 'none' option. $edit = ['card_1' => '_none']; $this->submitForm($edit, 'Save'); $this->assertSession()->responseContains(t('This is custom message for required field.')); } /** * Tests the 'options_select' widget (multiple select). */ Loading