Native browser form validation does not fire when submit buttons use #ajax

Created on 17 July 2017, over 7 years ago
Updated 18 March 2024, 8 months ago

Problem/Motivation

Modern browsers perform client-side validation for certain input fields. The easy example is for an input marked required.
This is only triggered when the browser detects a type="submit" being clicked.

When you attach an #ajax handler to a submit button, this seems to prevent that from correctly firing.

This is not a real validation problem, as we perform our own server-side validation. But it does negatively affect the UX.

Proposed resolution

TBD

Remaining tasks

Find a solution

User interface changes

Native validation will work for all submit buttons, not just non-Ajax ones

API changes

TBD

Data model changes

N/A

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
AjaxΒ  β†’

Last updated about 5 hours ago

Created by

πŸ‡ΊπŸ‡ΈUnited States tim.plunkett Philadelphia

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • The Needs Review Queue Bot β†’ tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

    Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

    Consult the Drupal Contributor Guide β†’ to find step-by-step guides for working with issues.

  • Status changed to Needs review over 1 year ago
  • last update over 1 year ago
    Custom Commands Failed
  • πŸ‡¨πŸ‡΄Colombia jedihe

    Re-rolling for D10.1.x. Also applies on 10.0.7

  • last update over 1 year ago
    29,283 pass
  • πŸ‡¨πŸ‡΄Colombia jedihe

    Fix CCF.

  • Status changed to Needs work over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Was previously tagged for tests which appear to still be needed.

    Also tagging for issue summary update as the current task is "Find a solution".

  • πŸ‡§πŸ‡·Brazil gabriel.passarelli

    I was able to make #73 work, but I had to add a custom code to my JS scripts. And the reason for this is that the patch on #73 fires an event,drupalAjaxFormValidate and will wait for the result of that event in order to check if it should trigger the AJAX submit or not, but it does not trigger the native browser form validation.

    So I had to implement my own code for this event and trigger the native browser validation.

    Drupal.behaviors.clientSideValidationAjax = {
        attach(context) {
          $(context).on("drupalAjaxFormValidate", (event) => {
            const form = $(event.target).closest("form")[0];
            if (!form.checkValidity()) {
              // This is the magic function that displays the validation errors to the user
              form.reportValidity();
              return false;
            }
            return true;
          });
        },
    };

    It's also important to highlight that if you have any additional #ajax to the form, that you don't want to trigger the native validation when that AJAX is performed, you need to add a formnovalidate attribute to your field definition in the form api. Like this:

        $form['select_with_ajax'] = [
          '#type' => 'select',
          ...
          '#attributes' => [
            'formnovalidate' => "formnovalidate",
          ],
          '#ajax' => [
            'callback' => '::ajaxWithoutNativeValidation',
          ],
        ];
    
  • πŸ‡§πŸ‡·Brazil gabriel.passarelli

    I was able to make #73 work, but I had to add a custom code to my JS scripts. And the reason for this is that the patch on #73 fires an event,drupalAjaxFormValidate and will wait for the result of that event in order to check if it should trigger the AJAX submit or not, but it does not trigger the native browser form validation.

    So I had to implement my own code for this event and trigger the native browser validation.

    Drupal.behaviors.clientSideValidationAjax = {
        attach(context) {
          $(context).on("drupalAjaxFormValidate", (event) => {
            const form = $(event.target).closest("form")[0];
            if (!form.checkValidity()) {
              // This is the magic function that displays the validation errors to the user
              form.reportValidity();
              return false;
            }
            return true;
          });
        },
    };

    It's also important to highlight that if you have any additional #ajax to the form, that you don't want to trigger the native validation when that AJAX is performed, you need to add a formnovalidate attribute to your field definition in the form api. Like this:

        $form['select_with_ajax'] = [
          '#type' => 'select',
          ...
          '#attributes' => [
            'formnovalidate' => "formnovalidate",
          ],
          '#ajax' => [
            'callback' => '::ajaxWithoutNativeValidation',
          ],
        ];
    
  • πŸ‡ΊπŸ‡ΈUnited States dswier

    Thanks for reporting your solution @gabriel.passarelli. I used the patch in #70 since we're still on 9.5, and then adapted your JS snippet into my own custom JS. With that combination, the forms we were trying to get both AJAX and native browser validation to work on are now working.

  • πŸ‡©πŸ‡°Denmark nicklasmf

    Following #75 works here as well on D10

  • πŸ‡ΊπŸ‡ΈUnited States joshua.boltz

    I have confirmed that the patch from #73 and the custom "clientSideValidationAjax " JS snippet/behavior logic from #75 added to my custom JS behavior allows this to work as desired on D10.

  • πŸ‡ͺπŸ‡ΈSpain purushotam.rai

    purushotam.rai β†’ made their first commit to this issue’s fork.

  • Merge request !5886Update ajax.js β†’ (Open) created by purushotam.rai
  • First commit to issue fork.
  • πŸ‡ΊπŸ‡ΈUnited States tregonia

    I have found that the changes in the latest MR completely override the `novalidate` attribute functionality in some of my forms. Specifically, forms with required fields, and a onchange (not a submit button) that triggers a rebuild of the form.

    In my case, I have products on a group and on a user. When adding a user, there is a select element for the company that when changed, triggers an ajax callback that filters a form rebuild that further filters the products that can be assigned. Adding this patch results in the `novalidate` on the `
    ` element getting ignored, and the ajax callback not being able to submit until all required fields are entered. Having only added this patch last week, reverting the patch out of the build results in the functionality working as expected.

    I think that this is by design; since this patch affects the `formnovalidate` attribute, that overrides the `novalidate` attribute.

Production build 0.71.5 2024