How to use a <.Live_file_input > in a <.simple_form>?

Buscar detalles

245 / 5,000

Resultados de traducción

Hi, I’m looking for a way to link this. <.live_file_input upload={@uploads.avatar} /> with a field in my database called xlsx_urls to save the urls of the files but I can’t find a way to do it

 <.simple_form
        for={@form_workbook}
        id="workbook"
        phx-submit="saveE"
      >
        <.live_file_input  upload={@uploads.avatar} />
        <.input field={@form_workbook[:name]} value = {@workbook.name}  type="text" label="Name" />
        <.input field={@form_workbook[:exel_file]}  value = {@workbook.exel_file} type="text" label="Ruta"/>
        <:actions>
          <.button phx-disable-with="Saving...">Save Workbook</.button>
        </:actions>
      </.simple_form>

<.live_file_input upload={@uploads.avatar} /> just enables your users to upload files via the form.

Once submitted, you have to consume the uploaded files and handle the resulting file paths in handle_event("saveE", workbook_params, socket).

For example, you could Map.put(workbook_params, "xlsx_urls", uploaded_file_paths) to add the urls to your form params.

Be sure to check out the Consume Uploads section in the documentation.

I currently have something like this and it allows me to save in my priv/static/uploads folder:

  def handle_event("save_upload", %{"workbook" => workbook_params}, socket) do
    uploaded_files =
        consume_uploaded_entries(socket, :avatar, fn %{path: path}, _entry ->
          dest = Path.join([:code.priv_dir(:imports), "static", "uploads", Path.basename(path)])
          File.cp!(path, dest)
          {:ok, "/uploads/" <> Path.basename(dest)}
        end)

      {:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
        
        IO.inspect(uploaded_files, label: "--------------------> guardo ?")
  save_workbook(socket, :action , workbook_params)
end

but the problem occurs when I want to join it with a table called xlsx_urls from my database… what I am looking to achieve is that the url remains in my database so I can consume it later

You won’t get urls. A form submits a stream that you consume, and client side, you have Blob/File. Perhaps use a hook on your form? Something like using the change event: you get a files = evt.target.files that you can store in an outer scoped variable. After this onchange, you can probably use a handleEvent("do-upload", () => self.upload("files", files) (probably need to be careful with the this, maybe define a self=this). The handleEvent can be triggered by a push_event("do-upload") when you want.

That is expensive for large files, I prefer to check first if I can move the files (File.rename)

and make the real save with async tasks

1 Like

uploaded_files is a list of paths to the saved uploaded files:

uploaded_files = ["/uploads/file1", "uploads/file2", ...]

You can save them in the database just like any other string. So in addition to save_workbook/3 you could also do something like:

Enum.each(uploaded_files, &create_xlsx_url(%{url: &1})

If your workbook schema has a xlsx_urls field (field :xlsx_urls, {:array, :string}, default: []) you could also add the urls to your workbook_params:

workbook_params = Map.put(workbook_params, "xlsx_urls", uploaded_files)
save_workbook(socket, :action , workbook_params)