Follow up of: #2509268: Inline errors repeated on child elements in module uninstall form.
Background
Since Drupal 8 form error messages are stored in $form_state and they have a direct relation with the form element causing the problem.
Currently all inline error messages are repeated on child elements (#tree => TRUE).
The inline docs of getError()
says:
Form errors higher up in the form structure override deeper errors as well as errors on the element itself.
As @bonjanz noted in #2509268-16: Inline errors repeated on child elements in module uninstall form:
The problem is coming from
FormErrorHandler::setElementErrorsFromFormState()
which calls$form_state->getError()
, which returns errors for parent elements as well.The #errors key was previously used to indicate "do I or one of my parents have an error", to add an error class when needed, but now it's also used to display the error message, hence the problem.
@yched shows the current need for this behavior in #2509268-25: Inline errors repeated on child elements in module uninstall form:
We do however have a lot of field widgets that rely on the current behavior when it comes to the task of "mapping a field constraint violation down to an actual form element" (i.e WidgetInterface::errorElement($violation)).
The default implementation in WidgetBase, which is good enough for most widgets, is "I'll flag the widget wrapper element as a whole, and the error will be displayed on every children (in most cases there's only one)". More complex widgets can, if they need, decide to do more fine-grained flagging if they have several child input elements.
That "catch all" default behavior :
- is the only default implementation that makes sense generically,
- is also what you want for violations that really are on the field itself (like a NotNull constraint for required fields, or the FeedUrl constraint for the feed 'url' field that seems to be causing the fails mentioned in #19) rather than on some specific property within the field.
Problem statement
As far as we know duplicate error messages on child elements are no problem in the current forms in Drupal 8, or are fixed on a case-by-case basis
Contrib modules with forms and custom forms however can have the problem of duplicate messages showing up on child elements.
There is however already a form element property that prevents this behavior. @dmsmidt in #2509268-54: Inline errors repeated on child elements in module uninstall form:
To prevent errors from showing up, we already have the property '#error_no_message'. This already gives us the possibility to hide messages on $elements.
Possible improvements
@dmsmidt and @tim.plunkett worked on finding a way to prevent the actual messages from bubbling up the #parents tree.
The patch in #2509268-17: Inline errors repeated on child elements in module uninstall form can be a starting point. To ensure BC the bubbling up behavior probably needs to stay.
We could add an element property to form elements that, when set to TRUE, prevents this behavior.
And / or add an extra parameter to setError()
and setError
that prevents the behavior.
This would make the DX much easier since not all child elements would need the '#error_no_message' set.
For D9 we should think about disabling the bubbling of the error messages by default.
Comments
Comment #2
dmsmidtComment #3
dmsmidt