svilen
LiveView Uploads: resuming on cancel with auto_upload
I’m currently implementing the brand new LiveView Uploads, using the auto_upload setting, and I have a situation which I’m not sure how to resolve.
The uploader is configured to handle multiple images, with auto_upload: true:
socket
|> allow_upload(:images,
accept: [".jpg", ".jpeg", ".png"],
auto_upload: true,
progress: &handle_progress/3,
max_file_size: 5 * 1024 * 1024,
max_entries: 20
)
The actual file upoad input is hidden, so we have drag and drop only.
When you drop a bunch a files, and they are all valid, the upload starts and everything works as expected. However, if there is a single file that’s invalid, the whole batch of files stops. I have implemented a cancel button so you can cancel individual files from the UI:
def handle_event("cancel-upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :images, ref)}
end
The problem I’m facing is that after I cancel the invalid file(s), the remaining valid files does not resume uploading. Unless I submit the form or add drag and drop more files, nothing will get uploaded.
I’m looking for a way to “retry” uploading files or trigger auto_upload again, if all entries on the uploader are valid. Does anyone have any ideas how to do it?
Here is my template markup (simplified version) just for completeness:
<%= live_file_input @uploads.images, class: "is-hidden" %>
<div class="dropzone" phx-hook="DragOver" phx-drop-target="<%= @uploads.images.ref %>">
Drag and drop your files here
</div>
<table class="uploads-in-progress table">
<tbody>
<%= for entry <- @uploads.images.entries do %>
<tr>
<td class="<%= if !entry.valid?, do: "has-text-danger" %>"><%= entry.client_name %></td>
<td><progress class="progress" value="<%= entry.progress %>" max="100"><%= entry.progress %></progress></td>
<td class="has-text-danger"><span class="is-clickable" phx-click="cancel-upload" phx-value-ref="<%= entry.ref %>">Cancel</span></td>
</tr>
<% end %>
</tbody>
</table>
Most Liked
svilen
I have a workaround, which is a bit of a hack… Here it is for anyone interested:
I noticed that live_view.js simply dispatches an input event to the drop target here so I created a hook that triggers the event:
Hooks.ResumeUpload = {
mounted() {
this.handleEvent('resume_upload', ({id}) => {
const dropTarget = document.getElementById(id);
dropTarget.dispatchEvent(new Event('input', { bubbles: true }));
});
},
};
The hook subscribes to a resume_upload event, which is triggered when you cancel an upload:
def handle_event("cancel_upload", %{"ref" => ref}, socket) do
socket =
socket
|> cancel_upload(:images, ref)
|> push_event("resume_upload", %{id: socket.assigns.uploads.images.ref})
{:noreply, socket}
end
and in the template I just had to find a place for the hook:
<div id="upload-section" phx-hook="ResumeUpload">
<!-- same code as before ... -->
</div>
I wonder if there is a better way to accomplish this 
envixo
Thanks for sharing the solution.
enkr1
This workaround is working fine but im just curious why is this not fixed/handled in the phoenix live view?







