Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
When using setErrorByName in a custom block's blockValidate the page will not save on submit and will not show the error or highlight the erred field.
How to reproduce:
- Create a new block programatically.
- Implement the blockForm method and add an extra text input field to the block form.
- Implement the blockValidate method and add a validation to your input field using $form_state->setErrorByName('your_input_text', t('Needs to be an interger'));
- In your new block settings fail the validation of your input text
- The form will not be saved but it won't display the error in your input field either.
Proposed resolution
Copy the form validation errors from the settings object to the $form_state object
Remaining tasks
None
User interface changes
None
API changes
None
Data model changes
None
Comment | File | Size | Author |
---|---|---|---|
#16 | interdiff-2649746-14-16.txt | 2.17 KB | gnuget |
#16 | block_config_form_does-2649746-16.patch | 3.57 KB | gnuget |
Comments
Comment #2
lahoosascoots CreditAttribution: lahoosascoots commentedComment #3
gnugetHi!
I've been reading the code to check why the error is not displayed and I found why, but I'm not sure yet how to fix it.
The problem is in the
BlockForm::validateForm()
method.There we have this code:
The important line is:
Which basically execute
BlockBase::validateConfigurationForm
and this method finally execute our$this->blockValidate($form, $form_state);
method.The problem is the errors of the block form are in the
$settings
object which is the variable to we passed to thevalidateConfigurationForm
method not in the$form_state
itself, that is why the reference is lost.What I tried to do to fix it was create a new method called setErrors() in the FormState class to we can do something like:
And this kind of work, it display the error but the input doesn't appear in red yet:
I will continue working on this to check what can be done in order to fix it.
David.
Comment #4
mallezieNot sure, but is this a similar bug as in #2645784: Error validation messages produced by image effect plugins not shown ?
Comment #5
claudiu.cristeaCan you post the steps to reproduce this error?
Comment #6
gnuget@Mallezie Yes it seems the same problem.
@Claudio.cristea sure I will update the summary.
Comment #7
gnugetComment #8
gnugetComment #9
claudiu.cristeaOK, first we need a patch that contains only the test, not the fix. That patch should fail and is the evidence of the error. Can you post such a test (maybe my test from https://www.drupal.org/node/2645784 is useful)?
Comment #10
gnugetSure, I'll do it.
I will assign this ticket to me and I will work on this tonight.
Thanks for your help.
Comment #11
claudiu.cristeaGreat! This also needs a summary update to follow our summary template. See https://www.drupal.org/issue-summaries
Comment #12
gnugetComment #13
gnugetComment #14
gnugetAlright.
Here the test and the patch with the fix.
Comment #16
gnugetI fixed some problems in this new patch, the main fix is to now the inputs turn red when there is a validation problem (which is the expected behavior), and a few nitpicks.
Patch and interdiff attached.
Comment #17
gnugetComment #18
tim.plunkettThis is a symptom of #2537732: PluginFormInterface must have access to the complete $form_state (introduce SubFormState for embedded forms), which if fixed properly, would make this obsolete.
If this is committed as a workaround, it should at least reference it in an @todo.
Comment #19
claudiu.cristeaLet's add here the @todo requested by @tim.plunkett. i added the same in #2645784: Error validation messages produced by image effect plugins not shown.
This can lie. For example the main form can have an error but the subform not. Then this will return TRUE. So, I don't see the gain. Since FormState protected $errors variable is initialised to an empty array, we'll have at least an empty array in $settings->getErrors(). I would remove the if().
Hmm. Sure we cannot perform this test with an existing block? The only condition would be that the block would embed an form, right?
You can insert directlly the array in ->drupalPostForm().
Can go inline.
Comment #20
claudiu.cristeaDiscussed on the other issue to focus on the issue that solves all cases like this. Instead of committing a workaround let's focus on the parent issue. Closing this as duplicate of #2537732: PluginFormInterface must have access to the complete $form_state (introduce SubFormState for embedded forms).