public function FormState::setErrorByName in Drupal 9
Same name and namespace in other branches
- 8 core/lib/Drupal/Core/Form/FormState.php \Drupal\Core\Form\FormState::setErrorByName()
Files an error against a form element.
When a validation error is detected, the validator calls this method to indicate which element needs to be changed and provide an error message. This causes the Form API to not execute the form submit handlers, and instead to re-display the form to the user with the corresponding elements rendered with an 'error' CSS class (shown as red by default).
The standard behavior of this method can be changed if a button provides the #limit_validation_errors property. Multistep forms not wanting to validate the whole form can set #limit_validation_errors on buttons to limit validation errors to only certain elements. For example, pressing the "Previous" button in a multistep form should not fire validation errors just because the current step has invalid values. If #limit_validation_errors is set on a clicked button, the button must also define a #submit property (may be set to an empty array). Any #submit handlers will be executed even if there is invalid input, so extreme care should be taken with respect to any actions taken by them. This is typically not a problem with buttons like "Previous" or "Add more" that do not invoke persistent storage of the submitted form values. Do not use the #limit_validation_errors property on buttons that trigger saving of form values to the database.
The #limit_validation_errors property is a list of "sections" within $form_state->getValues() that must contain valid values. Each "section" is an array with the ordered set of keys needed to reach that part of $form_state->getValues() (i.e., the #parents property of the element).
Example 1: Allow the "Previous" button to function, regardless of whether any user input is valid.
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => t('Previous'),
'#limit_validation_errors' => array(),
// No validation.
'#submit' => array(
'some_submit_function',
),
);
Example 2: Require some, but not all, user input to be valid to process the submission of a "Previous" button.
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => t('Previous'),
'#limit_validation_errors' => array(
// Validate $form_state->getValue('step1').
array(
'step1',
),
// Validate $form_state->getValue(array('foo', 'bar')).
array(
'foo',
'bar',
),
),
'#submit' => array(
'some_submit_function',
),
);
This will require $form_state->getValue('step1') and everything within it (for example, $form_state->getValue(array('step1', 'choice'))) to be valid, so calls to self::setErrorByName('step1', $message) or self::setErrorByName('step1][choice', $message) will prevent the submit handlers from running, and result in the error message being displayed to the user. However, calls to self::setErrorByName('step2', $message) and self::setErrorByName('step2][groupX][choiceY', $message) will be suppressed, resulting in the message not being displayed to the user, and the submit handlers will run despite $form_state->getValue('step2') and $form_state->getValue(array('step2', 'groupX', 'choiceY')) containing invalid values. Errors for an invalid $form_state->getValue('foo') will be suppressed, but errors flagging invalid values for $form_state->getValue(array('foo', 'bar')) and everything within it will be flagged and submission prevented.
Partial form validation is implemented by suppressing errors rather than by skipping the input processing and validation steps entirely, because some forms have button-level submit handlers that call Drupal API functions that assume that certain data exists within $form_state->getValues(), and while not doing anything with that data that requires it to be valid, PHP errors would be triggered if the input processing and validation steps were fully skipped.
Parameters
string $name: The name of the form element. If the #parents property of your form element is array('foo', 'bar', 'baz') then you may set an error on 'foo' or 'foo][bar][baz'. Setting an error on 'foo' sets an error for every element where the #parents array starts with 'foo'.
string $message: (optional) The error message to present to the user.
Return value
$this
Overrides FormStateInterface::setErrorByName
1 call to FormState::setErrorByName()
- FormState::setError in core/
lib/ Drupal/ Core/ Form/ FormState.php - Flags an element as having an error.
File
- core/
lib/ Drupal/ Core/ Form/ FormState.php, line 1055
Class
- FormState
- Stores information about the state of a form.
Namespace
Drupal\Core\FormCode
public function setErrorByName($name, $message = '') {
if ($this
->isValidationComplete()) {
throw new \LogicException('Form errors cannot be set after form validation has finished.');
}
$errors = $this
->getErrors();
if (!isset($errors[$name])) {
$record = TRUE;
$limit_validation_errors = $this
->getLimitValidationErrors();
if ($limit_validation_errors !== NULL) {
$record = FALSE;
foreach ($limit_validation_errors as $section) {
// Exploding by '][' reconstructs the element's #parents. If the
// reconstructed #parents begin with the same keys as the specified
// section, then the element's values are within the part of
// $form_state->getValues() that the clicked button requires to be
// valid, so errors for this element must be recorded. As the exploded
// array will all be strings, we need to cast every value of the
// section array to string.
if (array_slice(explode('][', $name), 0, count($section)) === array_map('strval', $section)) {
$record = TRUE;
break;
}
}
}
if ($record) {
$errors[$name] = $message;
$this->errors = $errors;
static::setAnyErrors();
}
}
return $this;
}