agonzalezro

agonzalezro

Liveview with a form that includes several changesets

Hi :wave:

I am trying to create a live view that shows a form. This form will allow you to create an snapshot per each product you own. The snapshots saves a quantity and a reference to the product.

There is another field rate that I will remove from the snippets for simplicity:

# snapshot.ex
defmodule xxx.Snapshots.Snapshot do
  ...

  schema "snapshots" do
    embeds_many :items, Item do
      field(:quantity, :integer)

      belongs_to(:product, Product)

      timestamps()
    end
  end

  ...

  def new_item_changeset(snapshot, params \\ %{}) do
    snapshot
    |> cast(params, [:quantity, :product_id])
    |> validate_number(:quantity, greater_than_or_equal_to: 0)
  end
end

I have this view:

# dashboard_live.ex
defmodule xxxWeb.DashboardLive do
  ...

  @impl true
  def mount(_params, session, socket) do
    current_user = Accounts.get_user_by_session_token(session["user_token"])

    products = Products.get_by_user!(current_user)

    items =
      products
      |> Enum.map(fn product ->
        params = %{product_id: product.id}

        Snapshot.new_item_changeset(
          %Snapshot.Item{
            product: product # preload
          },
          params
        )
      end)

    form =
      Ecto.Changeset.put_embed(
        Ecto.Changeset.change(%Snapshot{}),
        :items,
        items
      )
      |> to_form

    {:ok,
     socket
     |> assign(:page_title, "Dashboard")
     |> assign(form: form |> IO.inspect())
     |> stream(:products, products)}
  end

  def render(%{live_action: :show} = assigns) do
    ~H"""
    <.form for={@form} phx-change="validate" phx-submit="save">
      <%= for snapshot <- @form.source.changes.items do %>
        <div><%= snapshot.data.product.description %></div>
        <%!-- <div><%= product.type %></div> --%>
        <.input type="number" field={snapshot[:quantity]} />
      <% end %>

      <%!-- <%= for item <- @form[:items] do %>
        <.input type="number" field={item[:quantity]} />
      <% end %>
      --%>
      <button>Add snapshot</button>
    </.form>
    """
  end
end

I have several questions here:

  1. I have added the embeds_many in the schema because it was the only way I found to create a form with several changesets. Is it right?
  2. Is belongs_to the best way to scheme this? A user has N products where N can be dynamic through time. The snapshot is a snapshot (sorry) of that moment in time adding the quantity of products they own.
  3. I am able to list the product description with <%= snapshot.data.product.description %> however I don’t know how to make the <.input /> work as it is a changeset inside a changeset and not a form.

Any other suggestion/help would be more than welcome. I am trying to do this to understand LiveViews so I want to be the closest to the “credo” as possible.

Thanks!

Marked As Solved

Last Post!

agonzalezro

agonzalezro

In case it helps this is what the form has:

%Phoenix.HTML.Form{
  source: #Ecto.Changeset<
    action: nil,
    changes: %{
      items: [
        #Ecto.Changeset<
          action: :insert,
          changes: %{product_id: 1},
          errors: [],
          data: #Cleanhen.Snapshots.Snapshot.Item<>,
          valid?: true
        >,
        #Ecto.Changeset<
          action: :insert,
          changes: %{product_id: 2, rate_id: 4},
          errors: [],
          data: #Cleanhen.Snapshots.Snapshot.Item<>,
          valid?: true
        >,
        ...

And what I need to preload is the product inside that #Cleanhen.Snapshots.Snapshot.Item<>.

Where Next?

Popular in Questions Top

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
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
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement