TIL: LiveView toast after async work

In a Phoenix Liveview app, I recently had to do some work in an assign_async(export a video). In terms of UI, I wanted to:

  • show a toast(or flash message) at the beginning indicating the work has started.
  • show toast once the work is completed, or if it fails

This second requirement means that I couldn't use assign_async for the job. Instead, turns out I had to use start_async to start the task, and handle_async callbacks to add the success/failure toast messages.

Here's what my code ended up looking like:

  @impl Phoenix.LiveView
  def handle_event("export-video", params, socket) do
    {:noreply,
     socket
     |> put_flash(:info, "Export started...")
     |> start_async(:export_video, fn ->
       # Replace with actual export call here
       :timer.sleep(5_000)

       "Success!"
     end)}
  end

@impl Phoenix.LiveView
def handle_async(:export_video, {:ok, message}, socket) do
  {:noreply, socket |> put_flash(:info, message)}
end

@impl Phoenix.LiveView
def handle_async(:export_and_upload, {:exit, reason}, socket) do
  {:noreply, socket |> put_flash(:error, "Failed due to: #{inspect(reason)}")}
end