Hello!
I’m trying to use CSV to give LiveView users a downloadable report. I am getting confused by all the possibly outdated(?) info I’m finding here and elsewhere. I’m too new to Elixir and Phoenix to understand.
So far, I have a LiveView where the user uploads a CSV. I then process that and add some data, ending up with a list of maps like:
[
%{
"Carrier" => "T-Mobile",
"Country" => "USA",
"Email" => "",
"FirstName" => "Test",
"LastName" => "",
"MobileNo" => "12345678910",
"Status" => "Active",
"TemplateID" => "123",
"UniqueID" => "1234567"
},
...
]
I have a controller for the download:
defmodule JHWeb.ExportController do
use JHWeb, :controller
def create(conn, %{"download_data" => data}) do
file = data
|> CSV.encode()
|> Enum.to_list()
|> to_string()
conn
|> put_resp_content_type("text/csv")
|> put_resp_header("content-disposition", "attachment; filename=\"download.csv\"")
|> put_root_layout(false)
|> send_resp(200, file)
end
end
which is obviously cobbled together from code examples I could find. I have also tried:
file = File.open!("download.csv", [:write, :utf8])
data |> CSV.encode |> Enum.each(&IO.write(file, &1))
per the CSV documentation, but it also fails.
Finally, I can’t figure out what I’m supposed to do in the LiveView. I have a button:
<button :if={@download_data} phx-click="download_csv"
phx-disable-with="Processing..."
>Download CSV</button>
with an event handler:
def handle_event("download_csv", _params, socket) do
# Get Base URL
uri = socket.assigns.uri
base_url = uri.scheme <> "://" <> uri.authority
export_resp = Req.post!("#{base_url}/api/v1/export", json: %{download_data: socket.assigns.download_data})
{:noreply, socket}
end
I get a 500 error:
(Protocol.UndefinedError) protocol String.Chars not implemented for {“Carrier”, “T-Mobile”} of type Tuple
I don’t have enough of a mental model or frame of reference to know what I’m doing wrong, what the correct way is to do downloads from a LiveView, or how to proceed in general. Help is greatly appreciated.