Problem/Motivation
Non-ajax response is returned from the Ajax callback of form elements when "httpMethod" property is set to "GET". This is likely due to the Form Builder class not recognizing the correct request method of the request and causing user input to be loaded from the wrong request property. ($request->query vs $request->request). Because of that, the event subscriber of the form builder is skipped.
Steps to reproduce
Add "a #ajax" callback to any form element in form alter with "httpMethod" set to "GET"
Proposed resolution
Ajax callback should return the same response as using "POST" method.
With the change Ajax request type can be set to GET (POST by default) in place, we want to improve the performance of our forms which include elements that we have "#ajax" callback added programmatically. The callbacks of these elements are mainly used to refresh a view programmatically based on user's selection. However, after adding the "httpMethod" parameter to the "#ajax" array, the AJAX callback began returning the HTML of the home page instead instead of the old JSON response.
After doing a bit of debugging inside the Core's code, we found that the "formBuilder" class depends on the "isMethodType" method from "formState" class to determine where user input is stored and then determine whether a request is a regular or AJAX request based on if the user input is empty or not.


We then found that the "method" property retains its default value of "POST" regardless if the request is using GET or POST method and we don't see that the property is being set or updated anywhere. The actual method of the HTTP request is stored in another property called "requestMethod". Given our findings, since "isMethodType" is the method that's being used in formBuilder, we believe that the issue we encountered with our custom code's AJAX callback not being triggered stems from the "formBuilder" failing to locate user input in the request, leading it to misidentify the request as a regular one instead of an AJAX request.
I'm not sure if this is something that was overlooked in the previous issue or using GET isn't recommended (or allowed) in custom #ajax callbacks?
Any enlightenment would be appreciated.
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | iShot_2024-04-23_20.57.05.png | 212 KB | sker101 |
| isMethodType.png | 77.95 KB | sker101 |
Issue fork drupal-3443046
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
Comment #2
sker101 commentedComment #3
sker101 commentedComment #4
sker101 commentedComment #5
sker101 commentedComment #6
sker101 commentedComment #7
sker101 commentedComment #8
mradcliffeAdding the needs tests tag to write a failing test in addition to manual testing.
Comment #9
percoction commentedJust commenting here to update: I've started working on this at DrupalCon2024 Portland.
Was (I believe) able to reproduce the bug on 11.x branch on a DrupalPod. I say I believe because I receive an error using GET method where I don't with a POST method, but I am not sure how to inspect requests / set breakpoints in DrupalPod yet.
Going to work on adding a test to core to prove / reproduce the bug
Comment #10
percoction commentedPushed up two branches on the issue fork (they are basically the same, cloned from the 10.2.x branch).
The branches include two new FunctionalJavascript tests that test adding a AJAX callback to a Form programmatically utilizing each of the two HTTP methods GET and POST. The test using a POST AJAX callback should succeed and the test using a GET AJAX callback should fail, demonstrating the bug.
Going to remove the Needs tests tag - please let me know if we really need tests on a 11.x branch as well before removing this tag.
Comment #11
quietone commentedThis needs to be fixed on 11.x (our main development branch) first, and are then back ported as needed according to our policies. Also, 10.2 is in security mode now.