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.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

hchonov’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, ajax_option_suppress_required_fields_validation.patch, failed testing.

hchonov’s picture

Status: Needs work » Needs review
FileSize
14.18 KB

Integrated a check, if required is set...

cspitzlay’s picture

Priority: Normal » Major

I 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.

hchonov’s picture

Here a failing test demonstrating the use case.

Status: Needs review » Needs work

The last submitted patch, 5: test_generating_multiple_required_field_items_per_ajax.patch, failed testing.

hchonov’s picture

Status: Needs work » Needs review
FileSize
16.63 KB

and here the failing test with my fix.

The last submitted patch, 5: test_generating_multiple_required_field_items_per_ajax.patch, failed testing.

hchonov’s picture

As #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.

Status: Needs review » Needs work
hchonov’s picture

Status: Needs work » Needs review
FileSize
5.6 KB

Now checking in FormValidator::doValidateForm if there is an actual request existing before accessing its query.

tim.plunkett’s picture

The 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.

hchonov’s picture

Yes, 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.

Status: Needs review » Needs work

The last submitted patch, 14: 2476569-ajax-validation-test-with-custom-validation-14.patch, failed testing.

hchonov’s picture

Status: Needs work » Needs review
FileSize
5.57 KB

Excuse 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.

hchonov’s picture

And here again the patch including the extended test.

The last submitted patch, 16: 2476569-ajax-validation-test-with-custom-validation-16.patch, failed testing.

mgifford’s picture

Status: Needs review » Needs work

Patch needs re-roll.

mohit_aghera’s picture

mohit_aghera’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

amateescu’s picture

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

That'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 :)

hchonov’s picture

That'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 :)

It 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:

Description: Provides an array of sections which are parts of $form_state['values'] which should be validated, implying that sections which are not listed should not be validated. This is normally used in multistep forms in the case of a "back" button, for example, where '#limit_validation_errors' => array() would mean not to validate anything as form values on the current page are to be discarded anyway. #limit_validation_errors does not have any effect if #submit is not set. More discussion is in the form_set_error() documentation.
Values: array indicating sections of the $form_state['values'] which should be validated.

Further take a look at FormState::setErrorByName():

      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();
      }

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'd vote for a won't fix here :)

I hope you could reconsider this now :).

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

iyyappan.govind’s picture

FileSize
23.83 KB

Hi

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

iyyappan.govind’s picture

I have applied the patch also. But it is not working. Please help me to fix this issue. Thanks

geek-merlin’s picture

Issue summary: View changes

Thanks 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.

geek-merlin’s picture

Version: 8.6.x-dev » 8.8.x-dev
Issue tags: +Contributed project blocker
geek-merlin’s picture

geek-merlin’s picture

Let's see what el testbot says to this plain rebase.

Status: Needs review » Needs work

The last submitted patch, 36: drupal-2476569-36-ajax-validation.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

The last submitted patch, 36: drupal-2476569-36-ajax-validation.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

geek-merlin’s picture

OK. 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" ;-).

Status: Needs review » Needs work

The last submitted patch, 38: drupal-2476569-38-ajax-validation.patch, failed testing. View results

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

JAINV18’s picture

@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?

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mlncn’s picture

I think i am in the same situation as JAINV18, currently blocking development of Focused Entity Reference.

avinashm’s picture

Hi @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

function mymodule_form_form_id_alter(&$form, FormStateInterface $form_state) {
  $form['myfield']['widget']['#ajax']['#limit_validation_errors'] = array();
}

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.