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

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

CommentFileSizeAuthor
#70 1736308-70.patch27.75 KBvoleger
#68 1736308-68.patch9.47 KBvoleger
#67 1736308-nr-bot_8upg06nu.txt3.13 KBneeds-review-queue-bot
#66 1736308-66.patch8.25 KBvoleger
#63 drupal-ajax-data-loss-1736308-63.patch6.97 KBbrad.bulger
#61 drupal-ajax-data-loss-1736308-61.patch3.73 KBbrad.bulger
#57 interdiff-55_57.txt639 bytesgauravvvv
#57 1736308-57.patch6.94 KBgauravvvv
#55 1736308-55.patch6.92 KBjelle_s
#53 1736308-53.patch8.65 KB_utsavsharma
#53 interdiff_52-53.txt1.07 KB_utsavsharma
#52 1736308-52.patch8.65 KBjelle_s
#43 interdiff-1736308-41-43.txt574 bytesjeroent
#43 1736308-43.patch8.52 KBjeroent
#41 interdiff-1736308-40-41.txt518 bytesjeroent
#41 1736308-41.patch8.51 KBjeroent
#40 interdiff-1736308-39-40.txt3.92 KBjeroent
#40 1736308-40.patch8.83 KBjeroent
#40 1736308-40-test-only.patch4.71 KBjeroent
#39 core_ajax_form_submission_during_ajax_request_fix_d9-1736308-27.patch4.12 KBtrwill
#28 submitting_a_form-1736308-28.patch802 bytesedurenye
#26 core_ajax_form_submission_during_ajax_request_fix_d8-1736308-26.patch3.84 KBDedMoroz
#24 ajaxinterdiff.txt4.34 KBPavan B S
#24 core_ajax_form_submission_during_ajax_request_fix_d8-1736308-24.patch2.25 KBPavan B S
#12 core_ajax_form_submission_during_ajax_request_fix_d8-1736308-12.patch2.25 KBNephele
#9 core-ajax-form-submission-during-ajax-request-fix-1736308-9.drupal-7.x-do_not_test.patch2.45 KBNephele
#9 core-ajax-form-submission-during-ajax-request-fix-1736308-9.patch2.27 KBNephele
#5 ajax_form_test.zip1.18 KBkenneth.venken
#1 core-ajax-form-submission-during-ajax-request-fix-1736308-1.patch1.44 KBkenneth.venken

Issue fork drupal-1736308

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

kenneth.venken’s picture

Status: Active » Needs review
StatusFileSize
new1.44 KB

Attached is a patch with the proposed solution.

nod_’s picture

Version: 7.x-dev » 8.x-dev
Category: bug » feature

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

damien tournoud’s picture

Don't we also disable all the submit buttons during the AJAX request?

kenneth.venken’s picture

[Edited: Duplicate post]

kenneth.venken’s picture

StatusFileSize
new1.18 KB

Attached is a simple Drupal 8 test module that illustrates the behaviour. After you enable the module, visit /ajax-form-test and change some of the textfield values. The module will print the form_state['values'] as received by the ajax callback.

To reproduce:
1) Change the value of element 1 to 1
2) Change the value of element 2 to 2 during the ajax request of element 1.
3) Wait for both ajax requests to finish.

The output returned by the last ajax request will be

      "element1 => 'test data element1'
      "element2 => '2'

while the expected result would be

      "element1 => '1'
      "element2 => '2'
kenneth.venken’s picture

@Damien Tournoud: Submit buttons aren't disabled during the ajax request as far as i can tell.

Status: Needs review » Needs work
Nephele’s picture

Category: Feature request » Bug report
Issue summary: View changes
Priority: Normal » Major
Status: Needs work » Needs review
StatusFileSize
new2.27 KB
new2.45 KB

I'm changing this issue into a major bug, because it causes loss of data -- specifically, user input data on a form can be lost when the form is submitted, without warning or explanation.

In particular, this issue always causes loss of data if a user simply edits any textfield that uses an ajax callback, and then clicks the Save button. Because the blur event (the trigger for the ajax processing) occurs simultaneously with the submit event, the modified field is always disabled and therefore missing when the form data is submitted to the server. Users are likely to repeat their edit, get the same result, and simply conclude that it is impossible to make edits on the website.

Re: "the solution is kinda hacky". 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. Plus it is far preferable to telling users "Stop -- don't hit the Save button unless you have first made sure to click some other random location on your screen and then waited 5 to 10 seconds. Otherwise the Save button will NOT save your data."

I have tweaked the original patch and rerolled it against 8.0.x-dev. I'm also including a 7.x version of the patch, since I needed to roll it for my website.

Status: Needs review » Needs work
Nephele’s picture

Nephele’s picture

Status: Needs work » Needs review
abogomolov’s picture

@Nephele thank you! Patch works perfekt.

lokapujya’s picture

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

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.

vadim.hirbu’s picture

Thanks @Nephele. Patch #12 works like a charm

lokapujya’s picture

Issue tags: +Needs tests

It might be ok, but should 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.) Hopefully, it can also be tested.

berdir’s picture

Was just bitten by this on a project, definitely a bug IMHO and fairly hard to identify.

Not submitting a form until ajax sounds interesting but I guess that might also be more complicated to implement?

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.

_Archy_’s picture

Confirming that @Nephele's patch #12 fixes the issue. I think that his fix 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?

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.

tomz0r’s picture

Also confirming Nephele's patch #12 fixes the issue.

Pavan B S’s picture

+++ b/core/misc/ajax.js
@@ -658,12 +659,18 @@
+      // value is included in all submissions. As per above, submissions that use
...
+      // However, that does not handle IFRAME submissions, nor does it handle any

Line exceeding 80 characters, please review.

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.

DedMoroz’s picture

edurenye’s picture

Status: Needs review » Needs work

This is working, but IMHO not in the best way.

This could confuse the user, as blocking the submit this way, the user has to click again in the submit button to submit the form.

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.
At least this happens in 8.4.

edurenye’s picture

StatusFileSize
new802 bytes

This is not the way, but works. Just as a workaround for the people.

edurenye’s picture

My patch does not work either is getting the previous value :(

edurenye’s picture

Maybe we could try to do something like this somehow: https://stackoverflow.com/questions/4901899/action-on-blur-except-when-specific-element-clicked-with-jquery

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

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.

divined’s picture

It is not a right solution. Most cases need to wait untill ajax complete before submit.
Image uploading i.e.

So, the right solution, in my opinion, it is disabling submit buttons during ajax requests,

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.

jonathanshaw’s picture

It is not a right solution. Most cases need to wait untill ajax complete before submit.
Image uploading i.e.

So, the right solution, in my opinion, it is disabling submit buttons during ajax requests,

There are 2 separate issues:

1) We should disable the submit button during ajax requests

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 have that unrelated ajax happen first before other submit handling.

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

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.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: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should 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.

gilsbert’s picture

Hello my friends. This issue has more than 8 years and is a major because the data loss.
I'm sorry to put extra pressure on it specially because I'm not able to help to conclude it but are we getting a solution soon?

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

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

trwill’s picture

Version: 9.2.x-dev » 9.3.x-dev
StatusFileSize
new4.12 KB

Rerolling patch against 9.3.x

jeroent’s picture

Tried to add a test that checks if the right values are submitted.

jeroent’s picture

StatusFileSize
new8.51 KB
new518 bytes

Status: Needs review » Needs work

The last submitted patch, 41: 1736308-41.patch, failed testing. View results

jeroent’s picture

StatusFileSize
new8.52 KB
new574 bytes
jeroent’s picture

Status: Needs work » Needs review
eric_a’s picture

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

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should 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.

sukanya.ramakrishnan’s picture

This patch is a life saver. I was totally lost debugging in the backend code as to why my input value was getting lost.
After a long search, found this issue and the patch. Hope this is committed to core soon. Will save a lot of headache!!

Thanks a million!!

regards,
Sukanya

mohangathala’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Ajax

#43 is working for me.

quietone’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work
Issue tags: -Ajax

It is nice to see progress on an old issue, thanks everyone!

Reviewing the issue comments I see several that are questioning the solution, #2, #15, #18, #27, #32. I see that #21 supports the solution. Based on that it doesn't seem like there is consensus here on the solution. This needs some discussion. And the result placed in the Issue Summary.

I don't see a code review in this issue. That needs to be done as well.

This should also have a fail patch, to prove the fix is working.

I am removing the Ajax tag because this is in the 'ajax component', per the issue tag guidelines.

mohangathala’s picture

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

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should 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.

jelle_s’s picture

StatusFileSize
new8.65 KB

Reroll for 9.5.x

_utsavsharma’s picture

Status: Needs work » Needs review
StatusFileSize
new1.07 KB
new8.65 KB

Fixed CCF for #52.
Please review.

Status: Needs review » Needs work

The last submitted patch, 53: 1736308-53.patch, failed testing. View results

jelle_s’s picture

Status: Needs work » Needs review
StatusFileSize
new6.92 KB

Reroll against 10.1.x

smustgrave’s picture

Version: 9.5.x-dev » 11.x-dev
Status: Needs review » Needs work
Issue tags: +Needs issue summary update

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

gauravvvv’s picture

StatusFileSize
new6.94 KB
new639 bytes

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

capysara’s picture

Title: Submitting a form during an ajax request: field data not in $_POST. » Submitting a form during an ajax request or before ajax is triggered results in data loss
Issue summary: View changes
Issue tags: -Needs issue summary update

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.

capysara’s picture

Issue summary: View changes
mohangathala’s picture

brad.bulger’s picture

StatusFileSize
new3.73 KB

Reroll of patch in #57 for 10.3.x

jeroent’s picture

Patch #61 does not contain all newly added files.

brad.bulger’s picture

StatusFileSize
new6.97 KB

I recreated the patch again against 11.x. It applies cleanly to 10.3.x as well.

voleger made their first commit to this issue’s fork.

voleger’s picture

Status: Needs work » Needs review
StatusFileSize
new8.25 KB

Root cause of the issue: pointer devices (mouse, touchscreen) are allowed to interfere with the Ajax handler process while awaiting a response, leading to incomplete form submission and/or triggering another Ajax call with out-of-sync form data due to ongoing Ajax response expectations.

My proposed solution is to use a locking mechanism to cover two scenarios:
- Lock any form element that contains a defined Ajax handler and submit buttons from being interacted with by a pointer device during the current Ajax call processing;
- Lock any form element that contains a defined Ajax handler and submit buttons from being interacted with by a pointer device during focus on the form element with a defined Ajax handler;

My solution uses CSS property handling instead of additional event handling for a pointer device for a pointer device event locking mechanism. The reason: due to attempts to use the `disable` property or any other way of messing with event listener definitions, causing breaks in form implementations. Using the pointer-events CSS property minimizes the risk of breaking something during the lock mechanism.

Current Ajax handler implementations are working well with keyboard devices. Because the user has to navigate through the form elements to the form submit button, the Ajax handler has a chance to be executed and provide feedback to the user by rendering the throbber element while the Ajax request is being initiated.

It is currently not covered by the tests and needs an accessibility review.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new3.13 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

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

voleger’s picture

StatusFileSize
new9.47 KB

Upload the patch with MR updates

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

voleger’s picture

StatusFileSize
new27.75 KB
alphex’s picture

The patch in #70 works for me.... on my laptop... but it won't deploy on pantheon...

alphex’s picture

Patch 68 works, and did deploy to pantheon.

voleger’s picture

Be aware of the known locking issue in #68 related to the file upload widget. This widget uses a different event-triggering chain, which results in the form to which the widget belongs becoming locked.