romenigld

romenigld

How to validate an array of strings for the upload files in Phoenix LiveView

Hello Guys,
I was doing the course of the PraProg Phoenix LiveView Pro and I was trying to do a validation for the upload files.
For example If I try to put just the name of the desks and not put any file for upload, I would like to show the validation for upload a file.

I tried to add a validate_required for the photo_urls on the changeset:

 defmodule LiveViewStudio.Desks.Desk do
  use Ecto.Schema
  import Ecto.Changeset

  schema "desks" do
    field :name, :string
    field :photo_urls, {:array, :string}, default: []

    timestamps()
  end

  @doc false
  def changeset(desk, attrs) do
    desk
    |> cast(attrs, [:name, :photo_urls])
    |> validate_required([:name, :photo_urls])
  end
end

But if I put just the name for the desks, the photo_urls are not validated.
as you can see the log:

[debug] QUERY OK db=2.1ms queue=1.3ms idle=1529.6ms
INSERT INTO "desks" ("name","photo_urls","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["Testing", [], ~N[2021-04-19 17:20:41], ~N[2021-04-19 17:20:41]]

But on the application this values are not showed. It shows only the those which have photo_urls.
But If I try to list all Desks, like:
iex> Desks.list_desks()
The empty photo_urls are recorded:

  %LiveViewStudio.Desks.Desk{
    __meta__: #Ecto.Schema.Metadata<:loaded, "desks">,
    id: 17,
    inserted_at: ~N[2021-04-16 21:11:22],
    name: "Testing",
    photo_urls: [],
    updated_at: ~N[2021-04-16 21:11:22]
  },

How can I validate an empty array of strings for the :photo_urls?

Marked As Solved

romenigld

romenigld

When I arrived in home I was thinking in to inspect the values.
So I do this:

defmodule LiveViewStudio.Desks.Desk do
  use Ecto.Schema
  import Ecto.Changeset

  schema "desks" do
    field :name, :string
    field :photo_urls, {:array, :string}, default: []

    timestamps()
  end

  @doc false
  def changeset(desk, attrs) do
    desk
    |> cast(attrs, [:name, :photo_urls])
    |> validate_required([:name])
    |> validate_empty_photo_urls()
  end

  def validate_empty_photo_urls(changeset)  do
    photos = get_field(changeset, :photo_urls)

    IO.inspect(photos, label: "Photos")

    if Enum.empty?(photos) do
      changeset = add_error(changeset, :photo_urls, "must insert a photo!")
      IO.inspect(changeset, label: "changeset")
    else
      changeset
    end
  end
end

So in the log shows me this:

Photos: []
changeset: #Ecto.Changeset<
  action: nil,
  changes: %{name: "test"},
  errors: [photo_urls: {"must insert a photo!", []}],
  data: #LiveViewStudio.Desks.Desk<>,
  valid?: false

And I can see it was working the validations and it wasn’t inserted in the database when I click on the button Upload.
So I was seeking why not it was showed the error and the thing is not having the error_tag for the :photo-urls.

So I add the error_tag on the beginning of the drag-and-drop div:

  <div class="drop" phx-drop-target="<%= @uploads.photo.ref %>">
      <div>
        <%= error_tag f, :photo_urls %>
        <img src="/images/upload.svg">
        <div>
          <label for="<%= @uploads.photo.ref %>">
            <span>Upload a file</span>
            <%= live_file_input @uploads.photo, class: "sr-only" %>
          </label>
          <span>or drag and drop</span>
        </div>
        <p>
          <%= @uploads.photo.max_entries %> photos max,
          up to <%= trunc(@uploads.photo.max_file_size / 1_000_000) %> MB each
        </p>
      </div>
    </div>

And now it’s working! :laughing:
Thank you for the help guys, it was very helpful!

Also Liked

cenotaph

cenotaph

my apologies, different language mix up there! I have corrected my post

romenigld

romenigld

Yes I know in the course it doesn’t cast the :photo_urls.
But I was testing to put just the :name and no files for uploads.
And then I notice it was saving on the database, but they don’t are showing.
So I was trying to do a validate in the schema.
For now your help make more sense.
But it would be nice to do this on the schema.
I will review some books, I think I saw something which is possible creating a custom validation.
I just don’t know how to do it now.
thank you for reply @f0rest8!

sfusato

sfusato

It invokes the validator function to perform the validation only if a change for the given field exists and the change value is not nil. The function must return a list of errors (with an empty list meaning no errors).

  • when the value is nil, the validator function won’t even be called; I believe you defined :photo_urls as an array of strings with the default value being empty list;
  • you must return a list of errors, [photo_urls: "must insert a photo!"], in the error case
  • [] in the no error case

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement