I have a page that allows uploads via a modal. When you submit the form, it closes the modal.
The problem is that now I want to reuse that modal to upload a new file. If I simply show the modal again, it’s using the same file input and thus has a file associated with it already.
If I call allow_upload
again in my LiveView, it complains that the upload needs to be consumed or cancled, which I already did via consume_uploaded_entries/3
.
Here’s my code…
def handle_event("save", _params, socket) do
consume_uploaded_entries(socket, :avatar, fn file, entry ->
{:ok, file}
end)
socket = allow_upload(socket, :avatar, accept: ~w(.jpg .jpeg .png .svg), max_entries: 1)
{:noreply, socket}
end
And here’s the error:
** (ArgumentError) cannot allow_upload on an existing upload with active entries.
Use cancel_upload and/or consume_upload to handle the active entries before allowing a new upload.
How can I reset the uploads so I can use them again on the same live view page?
1 Like
Hmm, haven’t tested this but maybe try using disallow_upload/2
to first revoke the previously allowed upload before re-allowing it?
def handle_event("save", _params, socket) do
consume_uploaded_entries(socket, :avatar, fn file, entry ->
{:ok, file}
end)
socket =
socket
|> disallow_upload(socket, :avatar)
|> allow_upload(:avatar, accept: ~w(.jpg .jpeg .png .svg), max_entries: 1)
{:noreply, socket}
end
Alternatively if you wanted to keep previous “rounds” of uploads, you could potentially use a :round
assign to pass allow_uploads
a dynamic name e.g.
def handle_event("save", _params, socket) do
consume_uploaded_entries(socket, :avatar, fn file, entry ->
{:ok, file}
end)
socket =
socket
|> assign(:round, socket.assigns.round + 1)
|> allow_upload(
String.to_atom("avatar_#{socket.assigns.round}"),
accept: ~w(.jpg .jpeg .png .svg), max_entries: 1
)
{:noreply, socket}
end
I tried that and it didn’t work. I also tried a few other things and ultimately gave up and kinda redesigned my whole page.
I kinda want to make an example repo and get community feedback for what the best way to do this is. It’s such a common pattern: user edit page, but allow for avatar cropping, rotating, editing via a modal and using cropperjs.
I got it all working, and tbh, the code is actually pretty nice and clean. It does use a Phx Hook, but the Javascript is surprisingly small. The problem was that it took me three days to get there.
1 Like
Hmm, was your goal was to let users choose between a modal to edit the existing uploadeds avatar image and another to upload a new avatar image to replace the one they had previously uploaded?
Regardless, glad you got something working in the end and I’d be interested in seeing what you came up with if you do end up making an example repo.