Submitting a form during an ajax request or before ajax is triggered results in data loss

Created on 17 August 2012, about 12 years ago
Updated 5 September 2024, 2 months ago

Problem/Motivation

Ajax elements are temporarily disabled to prevent the user from changing the element’s value during an ajax request. The change event is triggered when the field loses focus. If the user hits submit without losing focus on the field (i.e., select the textfield, change its value, and then directly click the save button of the form), then the value of the field is not saved. If the field is required, the submit validation will fire and throw an error indicating that the field is empty. If the field is optional, then the form submits, but the value is silently not saved, resulting in data loss.

The reason AJAX elements are disabled is to prevent the user from changing the element's value during the request. Ideally we should make the element readonly but the readonly property isn't available for all input elements. The current implementation uses the jQuery Form plugin's options.extraData to post the data of the disabled field. This works fine if there's only one active ajax request.

Steps to reproduce

This issue can be tested using the redirect contrib module out-of-the-box, without any specific module configuration, see #3057250 🐛 Validation issue on adding url redirect Needs review

Install & enable the redirect module

Steps:

  1. Navigate to admin/config/search/redirect/add
  2. First add the TO field value,
  3. Then click the PATH field and fill the values
  4. Without using tab in the keyboard or clicking outside of the field, click the save button (after filling the PATH field without clicking outside of that field, directly click the save button).
  5. There is a validation error saying that Path field is required.

Alternative steps

  1. Start at the target node
  2. Click Add redirect URL and you land on the pre-populated form
  3. Click in Path
  4. Enter URL
  5. Click Save or hit enter.
  6. There is a validation error saying that Path field is required.

Note: there’s a custom module in #5 that may be used to reproduce the issue, but it’s 12 years old at the time of updating this IS so it may or may not apply anymore.

Proposed resolution

Original proposed solution: Create a hidden input element for any ajax-disabled element and remove it when the ajax event finishes.
Updated proposed solution: Determine a better event type to be used to fire the ajax change.

Tl;dr, as of comment #58. The original proposed solution has been an effective workaround for several people, but it should be considered a workaround instead of a core fix because there hasn’t been a strong case for its use and it doesn’t fully address the root of the problem. According to the issue discussion, there’s wide support for disabling the submit button while ajax is running.

However, disabling submit may be out of scope here; this ticket describes behavior that may not be resolved by disabling the submit button while ajax is running since, in this case, the submit button is clicked before ajax starts.

Much longer summary of comments and discussion around the original proposed solution (as requested in #49) thru #58:
#2 & #15 are questioning the solution

not a bug as far as I can tell. And the solution is kinda hacky.

There must already exist a more standard way of dealing with this?

#9 responds to those comments:

The solution is functionally equivalent to putting the value into extraData: jquery.form.js puts all the extraData values into hidden input elements. If the jquery developers use this mechanism to add data to the submitted form, presumably it is the most reliable mechanism.

#18 & #27 & #30 & #32 are generally making the case that the submit button should not be available while ajax is running.

consider other solutions too. Such as: make the submit to wait for the blur to finish (or have the submit function perform the blur before submitting.)

working, but IMHO not in the best way… I think that after the AJAX call finishes, we should trigger the submit or give the validation error in case the field validation did not pass.

if we lose the focus for the submit button, we do not run AJAX call.

Most cases need to wait until ajax completes before submit. Image uploading i.e. So, the right solution, in my opinion, it is disabling submit buttons during ajax requests.

#19 & #21 make arguments against disabling the submit button

might also be more complicated to implement

[The proposed solution] is better than waiting for the ajax to complete. Either way we have to do validation again (obviously when submitted) so why wait for it?

#34 & #58 describe 2 separate issues here:

  1. We should disable the submit button during ajax requests to prevent users from submitting before we get the ajax response back.
  2. If clicking the submit button triggers an unrelated ajax request (as can happen e.g. if the ajax request is triggered by a changing textfield and clicking the submit button is the first thing a user does after typing in that textfield) then allow that unrelated ajax to happen first before other submit handling.

#58 argues that disabling submit while ajax is running isn’t the solution to this issue.

The problem described here is that the change event isn’t triggered until the text field loses focus, which can cause data loss because a user can submit the form without losing focus on the field, but before ajax ever runs. In other words, the form gets submitted, but ajax was never triggered, so the value isn’t saved. I think that further discussion should be around determining what type of event should be used to fire the ajax change.

Remaining tasks

Confirm the solution
Separate "disable the submit button during ajax" into a new ticket (or link to existing ticket)
Review
Commit

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Ajax 

Last updated about 17 hours ago

Created by

🇧🇪Belgium kenneth.venken

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

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

  • last update about 1 year ago
    Custom Commands Failed
  • 🇧🇪Belgium jelle_s Antwerp, Belgium

    Reroll against 10.1.x

  • Status changed to Needs work about 1 year ago
  • 🇺🇸United States smustgrave

    #49 called for issue summary update which believe still needs to happen.

  • 🇮🇳India gauravvvv Delhi, India

    Fixed, CCF in #55. Attached interdiff for same. leaving as NW, as issue summary still needs to update.

  • last update about 1 year ago
    30,147 pass
  • 🇺🇸United States capysara

    I updated the IS and title based on the discussion to date and my assessment of the issue. The summary of my summary is: there isn’t sufficient support for the original proposed solution as a core fix, but there is overall support and arguments in favor of disabling the submit button.

    I agree with #34 that there are 2 separate issues here.

    I think that submit should be disabled so that the form can’t be submitted while the ajax change call is running and before the server has responded. If you're going all the way to the server for a change event, it's probably important that it finishes and, if that's the case, the submit button should be disabled until the form is ready to be interacted with again. Since the ajax change call response can modify the values in the form, the user should not be able to submit the form with just the values they provided in the field (e.g., entity reference fields that rely on ajax change events).

    However, I don’t think that disabling the submit button addresses the reported issue and, IMO, would unnecessarily expand the scope of this ticket.

    The problem described here is that the change event isn’t triggered until the text field loses focus, which can cause data loss because a user can submit the form without losing focus on the field, but before ajax ever runs. In other words, the form gets submitted, but ajax was never triggered, so the value isn’t saved.

    I think that further discussion should be around determining what type of event should be used to fire the ajax change.

Production build 0.71.5 2024