Problem/Motivation
At the moment we only have #limit_validation_errors for form elements of type button and submit. Using it it is possible to turn off validation completly or enable it only for desired regions. But there is no option to say what should not be validated.
Let's look at a simple example.
We have a form structure, which enables us to add more items to the form through ajax. Each of this items might have a required field. When the user submits the ajax call to add another item the form is automatically validated and if the user decided first to generate couple of items and then fill out the required fields in each of them, she will not be able to do this, as she is going to get error saying that some of the fields are required and a new item will not be generated.
Now the developer has the option to suppress the whole validation with setting
#limit_validation_errors = array()
But by using this even the custom validation introduced by the developer will be suppressed, e.g. the user should get a validation error, if she generated more than 10 items.
Instead there should be a possibility to generate items with required fields without filling them out and they should be validated only when the whole form is submitted and not on each ajax call.
For another description / use case see #33.
Proposed resolution
Introduce a new setting for the form control '#ajax' called 'suppress_required_fields_validation', which when set to TRUE, will force the FormValidator to skip validation of required fields for the ajax call this setting was set for.
A form element might then set the ajax form control with the setting suppress_required_fields_validation like this:
'#ajax' => array(
'callback' => 'my_custom_ajax_callback',
'wrapper' => 'my_custom_wrapper_id',
'effect' => 'fade',
'suppress_required_fields_validation' => TRUE,
),
Remaining tasks
User interface changes
none
API changes
New setting 'suppress_required_fields_validation' for the form controll '#ajax'.
The patch commited with the issue shows the changes needed to achieve this.
Comments
Comment #1
hchonovComment #3
hchonovIntegrated a check, if required is set...
Comment #4
cspitzlayI can think of another use case that I find even more strange (and unfriendly to the user):
Suppose you had an "add item" and a "remove item" ajax button to add and remove elements with required fields on them.
Now the user can click "add another item" and easily get their new element. But to remove it he needs to enter all the required fields to make the validation pass so he is allowed to delete the element again.
Comment #5
hchonovHere a failing test demonstrating the use case.
Comment #7
hchonovand here the failing test with my fix.
Comment #10
hchonovAs #2263569: Bypass form caching by default for forms using #ajax. made several big changes, the previous patch will not apply anymore and needs to be adjusted.
So here a new version of the patch including the test.
I've also simplified the patch a lot.
Comment #12
hchonovNow checking in FormValidator::doValidateForm if there is an actual request existing before accessing its query.
Comment #13
tim.plunkettThe new test also passes if we just empty out #limit_validation_errors.
Why can't we just do it this way?
Maybe more test coverage will help illustrate.
Comment #14
hchonovYes, it works with the #limit_validation_errors as described in the IS, but as long as we have custom validation funcitons, which should run e.g. for a specific content type limit the field up to 2 items, then with #limit_validation_errors set the custom validate function will not set an error at adding the third item.
Here a new test demonstrating this use case, where the last assertion should fail.
Comment #16
hchonovExcuse me, I forgot to set the field as required in the last patch, but actually it makes no difference, with the #limit_validation_errors set to an empty array, no custom validation will be able to set errors.
Here again the test only with the field set as required.
Comment #17
hchonovAnd here again the patch including the extended test.
Comment #19
mgiffordPatch needs re-roll.
Comment #20
mohit_aghera CreditAttribution: mohit_aghera as a volunteer and at Axelerant commentedApplied patch in #17
Working fine. Updating patch.
Comment #21
mohit_aghera CreditAttribution: mohit_aghera as a volunteer and at Axelerant commentedComment #27
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThat's.. not true! I'm pretty sure you can use '#element_validate' together with '#limit_validation_errors = []' on a form element and the element validation handler will be called. I'd vote for a won't fix here :)
Comment #28
hchonovIt is not true, that it is not true, because if
'#limit_validation_errors'
is an empty array then all messages are being filtered away.Take a look at the Form API documentation:
Further take a look at FormState::setErrorByName():
This means that if
'#limit_validation_errors'
is an empty array, then the $record variable will stay FALSE and no errors will be recorded.I hope you could reconsider this now :).
Comment #31
iyyappan.govindHi
I am using Drupal Version 8.6.1. I have same problem in select drop-down ajax( a required field). I had this issue in Drupal 8.5.x. So I updated the Drupal to 8.6.1 but issue is not fixed. Please find the attachment
Comment #32
iyyappan.govindI have applied the patch also. But it is not working. Please help me to fix this issue. Thanks
Comment #33
geek-merlinThanks everyone for working on this! This bit us too and hard.
Our use case is the Ajax Dependency module. (Which in turn we need for our distribution's "conditional fields", as the jS-based conditional field module is too limited and imho currently broken beyond repair.)
On our organisation profile, we have an org_type field, which may be business, or nonprofit, or both, but must not be empty and thus is required. Using said module, we change access to other fields (like refs to nor-profit or non-profit taxonomy terms).
This issue bites us e.g. if a user 1) erroneously chooses 'nonprofit' 2) removes the 'nonprofit' checkmark, then the ajax call breaks as the reqired field now is empty thus invalid.
Note that setting nonrequired or limiting validation or hacking #element_validate is not an option, as the field must be required in the final submit. So we need a solution where there is no validation on ajax (exactly: the ajax triggered by a field change), but not on submit.
I even wonder if there is a use case for validating ajax-on-field-change that is a form rebuild and not a submit.
Comment #34
geek-merlinComment #35
geek-merlinComment #36
geek-merlinLet's see what el testbot says to this plain rebase.
Comment #38
geek-merlinNow with CS fixes.
Comment #40
geek-merlinOK. The rebased patch did not fix my use case. Also i realized that #limit_validation_errors on the ajax-on-value-change element fixes my use case.
To summarize:
* To suppress all validation when we want to only rebuild the form, use #limit_validation_errors=[]. It also works on ajax-on-value-change elements (which i did not realize first, also see the related docs issue)
* What the OP needed was to suppress only some validation on an element, but not their custom validation
So no contrib blocker at all, and "sorry for the noise" ;-).
Comment #45
JAINV18 CreditAttribution: JAINV18 as a volunteer commented@geek-merlin - How did you resolve your issue with #limit_validation_errors ?
I am facing this issue a lot when having multiple select fields dependent on each other, once selecting a parent field the child field gets populated but when I change the parent field again, I get an error -
"An illegal choice has been detected. Please contact the site administrator."
I tried using limit_validation_errors on all the fields but no luck.
Can you please tell me where did you use it - in the form_alter or ajax_callback?
Comment #47
mlncn CreditAttribution: mlncn at Agaric for Drutopia, Portside, Teachers with GUTS commentedI think i am in the same situation as JAINV18, currently blocking development of Focused Entity Reference.
Comment #48
avinashm CreditAttribution: avinashm as a volunteer and commentedHi @JAINV18 and @mlncn
I was facing the same issue and used #limit_validation_errors property to fix it.
Here is the sample code.
NOTE: Reference taken from (#12) https://www.drupal.org/project/business_rules/issues/3051993