I have a custom module that has a few sections that utilize Ajax updates. I also have a "managed_file" field (Form API).
The ajax works fine and updates two dependent fields, but the managed_file loses the form_state after I hit the Upload button.
If I only select the drop-down ajax field, then the $form_state['values'] is updated and retains the values for the fields that exist in the form. However, if I select a file to upload and click on the "Upload" button that is generated by the managed_file element, the $form_state['values'] seems to get reset and the only thing that is present there is the ID of the file that got uploaded. Anything else that was in the $form_state['values'] prior to the upload is lost and the drop-down dependency is broken.
I've put together a quick example (I'm not able to post it here - I'm missing a privilege - I'll try to resolve that). It contains a drop-down box that updates the description of a text field and under that is a managed_file upload field.
Steps to re-create issue:
1. Select an option from the drop-down menu
- you'll see the form_state['values'] be dumped on the screen
2. Enter any text in the textfield
3. Click "Browse" - select a file (.txt file)
4. Then click "Upload"
- you will see the $form_state['values'] be dumped on the screen any it will only contain the file_upload and file_upload_button values (file_upload' => 'SOME_ID_HERE', 'file_upload_upload_button' => 'Upload',)
Any help would be appreciated.
I can use simple "file" to get around this issue, but I was wondering if anyone else had encountered this problem and/or if there is a solution for it.
Comments
FAPI ajax form with managed file Solution
I think I managed to answer my own question. I traced the issue I was experiencing to the “file” module, part of the Drupal Core. More specifically to the “file_ajax_upload” and “file_managed_file_process” functions of file.module.
The issue comes down to the way that Ajax requests are processed based on whether they use “PATH” or “CALLBACK” or both.
Here is the code snippet I am referencing (I’ve removed the variable declarations because it’s not letting me post them here for some reason):
The issue has to do with the sequence of execution on the “Upload” button. The Ajax “path” events get executed first and then the button’s “submit” ('file_managed_file_submit') function gets executed. The issue is that in the ajax PATH execution, the Ajax attempts to get the form state from the cache (ajax_get_form() ). The form_state[‘values’] does not seem to be cached and when other Ajax events take place on the original form, these values are lost when a file upload takes place – i.e. form_state[‘values’] is overwritten. This may be an issue in my setup, but I did try everything in the book to enable proper caching, excluding the manipulation of form_state[‘storage’], which I know would have worked.
The Solution.
The 'file_ajax_upload_callback' function is essentially a carbon-copy of the 'file_ajax_upload', with less than 10 lines of code modifications
This modification worked for me. It’s not ideal because it is modifying part of the drupal Core, but it makes sense to preserve the form state throughout the form processing.
P.s. I am not using a multi-step form.
callback without hacking core
you can get the element to use a callback instead of a path without hacking core. Add a #process element to your managed_file:
and then use that function to alter the managed_file element:
Joseph Cheek, Founder
CEO and Drupal Architect
The ZDS Group, Salt Lake City, UT, USA
https://zds.group/
Drupal consulting for media, publishing, and government
Hi Joseph, is it possible to
.
Thanks for taking the time to
Thanks for taking the time to explain your fix for this. I can't seem to get this working and it's a nightmare because my client has seen the upload field work previously and now I'm saying they can't have it, I'm explaining there is a bug and they are clueless and now think their website has a virus. But anyway, I have copied the file_ajax_upload function, but not sure if I have made the correct modifications as I am getting an error which states - Notice: Undefined index: #suffix in file_ajax_upload_callback()
Here is the modified function
Here is the other part of my
Here is the other part of my code, if anyone can help with this I am willing to pay, please leave a message
what about if i clone a file input programmatically?
Hi there,
I am trying to create additional 'add more' button to duplicated/clone certain input fields inside a form. I managed to control it all except for the 'managed_file' field. Although the managed_file 'clones' are working (i.e.: i can click on it to choose file), but those 'clones' are always losing the form_state and when i do a file_load on it, it gave me error. Is there something that i missed out here? maybe i need to bind the clones into a different trigger/function?
Any help would be good here.
Thanks!
jQuery solution to this problem
I was facing the same issue, so I hacked together some jQuery which solves the problem.
Basically, what I'm doing is calling the Attribute selection again after the Upload button is clicked. This way the image gets uploaded and the attribute selection gets saved.
Then, on an ajaxComplete event, this code gets fired:
If anyone cares to optimise my hacked code, be my guest.
In the meantime, I hope this helps you out.