[#4821] Persist profile attached documents through validation errors#5115
Conversation
…ion errors Use direct uploads for multiple file input so that file blobs remain available even if the model fails to save due to validation errors. - Submit hidden fields containing the signed_id of attached but unpersisted documents so that previously selected documents will be saved on the next successful form submission - Hide the native file input to prevent "No file chosen" from appearing when files were selected before a validation error - Use a custom button and file listing to display selected files during the current selection or on form re-render
dorner
left a comment
There was a problem hiding this comment.
All OK on my end.
@danielabar I think it's pretty nuts that this (which seems to be a common pattern) is so complex to get working. I'm wondering if there's a way to package this up into either a PR to Rails/Stimulus or a separate gem/package - it seems like a good open source opportunity.
|
@danielabar: Your PR |
Thanks for the suggestion! Yes this definitely seems like something that might be easier resolved from within Rails rather than in application code. |
Resolves #4821
Description
This is the final part 3 of improvements to editing partner profile Attached Documents section. It fixes the following situation:
There are a few moving parts to solve this:
1. Direct Uploads
The first part of the solution is to use direct uploads feature of Active Storage (already enabled via a previous PR). This ensures that the selected files are persisted to the storage service, and written as new records in
active_storage_blobstable, via ajax requests, even if the model didn't get saved on form submission.2. Submit hidden signed_id
When direct uploads is enabled, each document's
signed_idis accessible from the partner profile model, even if it failed to be saved due to validation errors. So the form partialapp/views/partners/profiles/step/_attached_documents_form.html.erbcan iterate over these and submit hidden field(s) for each document that was attempted to be attached, but not persisted. This allows Rails to associate these files to the model, upon the next successful form submission. The file names are also available from the model.3. Display to user previously selected files
It's one thing to have the signed_id's as hidden fields, it's quite another to let the user know that we still have their files so they don't need to select them again.
The native file picker (which is rendered from the
file_fieldform helper), has afilesattribute, and when its null/empty, it displays "No files selected". But the only way thefilesattribute of the native picker can be populated is from the user literally clicking on the "Choose file" button. This means that in the form validation error case, even though we still have the user's file selections, the native file picker will show "No file selected".It would be nice if we could set the
filesattribute of the native file picker via JavaScript, but this is not supported - see MDN on file input type for details.The solution then is to hide the native file input (still functional though) and instead render a custom "Choose files" button that when clicked, delegates to the native file picker. This is handled via a Stimulus controller
app/javascript/controllers/file_input_controller.js. This controller was introduced in a previous PR related to attached documents. At the time the only purpose was to customize the display of selected files (because the native file picker only displays number of files chosen, not the actual file names).Now the Stimulus controller is enhanced to accept a value Array of file names, and if provided, display these as the selected files.
Type of change
How Has This Been Tested?
For manual testing - follow the steps in the description. When the form re-renders with validation errors, scroll down to the "Attached Documents" section, open it up, and you should see your previously selected files are still rendered as "Selected files". Then if you fix the validation error(s) and click Save Progress, the attached documents should be saved.
For automated testing - see
spec/system/partners/profile_edit_system_spec.rb, new test added:it "persists multiple file uploads when there are validation errors" do...Screenshots
The native file picker for attached documents is hidden and a new custom button is displayed in its place:

After user selects some files, they're shown in a custom listing (this behaviour was added in a previous PR, but now a sub-header of "Selected files" is also rendered to make it clear these are what user just selected):

If form re-renders with validation errors, and user previously selected files, they are preserved - i.e. rendering looks the same as if they had just selected those files:

After user fixes validation error and Saves Progress again, the preserved files are now attached:

Here's what it looks like with a combination of existing attached files, plus a few new ones selected:
