Forms with live_file_input consume files when saving even if form is invalid

I have a form to edit a model with name and images attributes. Name is a string (min 3 chars), images is an array of string.
I’m using the example code from the official docs to implement the multi file upload using live_file_input to populate the images field.

When clicking on the submit button the save event handler is triggered, consuming files and copying them to the static folder.

If the form has no errors, the changeset validations are correct and the model is persisted.
If the form has an error (for example when the name is less than 3 chars):

  • the files are consumed
  • then the changeset validations are executed and the changeset is marked invalid
  • then the invalid changeset is re-rendered again, so that the user can fix the errors, but by now the files selected are gone (as they are already consumed).

What I have learned:

  • live_file_input does a preflight request when submitting that, if there is an error in the live_file_input, it does nothing and the submit is aborted until errors are fixed. This doesn’t take into account any other error on the form.
  • I might do the changeset validation on the save handler and only then try to consume the files and save the model, but it feels like the validate handler is the place where this logic should be, not the save handler
  • Maybe a boolean option might be useful in the allow_uploads to enable/disable saving. We could use it to control the live_file_input submit behavior from the live_view side by forcing the preflight checks to abort the submit if it is set to false. Something like:
     # on mount/update:
       is_valid = true
       |> allow_upload(:images,
         accept: ~w(.png .jpg .jpeg),
         max_entries: @max_entries,
         max_file_size: @max_file_size,
         valid: is_valid
     # on validate:
       is_valid = some && business && validation
       |> allow_upload(:images,
         valid: is_valid

I have a working example that shows this behavior here [1]. Just go to localhost:4000/products, add two images and put a name with one char to see the validation error on the name field and submit. The page reloads but the files are gone.

Is there a way for the save operation to honor both form errors and live_file_input errors before attempting the consumption of files and saving the model?

Thanks in advance for your insights

[1] GitHub - miguelcoba/mercury at official-live-file-input-docs

:valid isn’t a known option :slight_smile: (EDIT: sorry reading comprehension on my part, it was a suggestd feature :). You need to conditionally consume the file only if the data is valid on your handle_event("save".

I don’t think such a feature makes sense because you can and should only consume the file based on the validity/and or successful persistence of your data. So standard Elixir primitives apply with if/else/case etc.

Hey, Chris, thanks, that’s what I suspected. I’ll do it that way!

Thanks for the fast response.