Hey, I’m using a inputs_for
to render multiple fields, each with a input.
<.inputs_for :let={item} field={@form[:items]}>
<td>
<.input type="number" field={item[:quantity]} min={0} max={25} />
</td>
</.inputs_for>
An item is a embeds_many on a parent schema:
embeds_many :items, Item, on_replace: :delete do
@derive Jason.Encoder
field :name, :string
field :image, :string
field :variant_id, :string
field :quantity, :integer
field :price, :decimal
end
Unfortunately, the hidden field generated by inputs_for
is the following, which includes “_persistent_id” and not “id”:
<input type="hidden" name="draft_order_creation_form[items][0][_persistent_id]" value="0">
Which makes so that when I change values in the browser, the params submitted do not contain the element id, bu rather the _persistent_id
"items" => %{"0" => %{"_persistent_id" => "0", "quantity" => "1"}}
Because of that, Ecto can’t match on id, and thus can’t update the value when doing the cast_embed.
Am I missing something ?
Any help would be much appreciated!
inputs_for
does include hidden fields: phoenix_live_view/lib/phoenix_component.ex at v0.20.17 · phoenixframework/phoenix_live_view · GitHub
If they are not showing up, it is either because the field is nil (or maybe the resource is not persisted), so there is no ID to go by. Here is the logic for getting fields from Ecto: phoenix_ecto/lib/phoenix_ecto/html.ex at main · phoenixframework/phoenix_ecto · GitHub
2 Likes
Hey @josevalim thanks for getting back to me!
Got it, the resource is in fact not persisted, but I am passing an ID value, this is the input to my to_form
call.
#Ecto.Changeset<
action: :validate,
changes: %{
items: [
#Ecto.Changeset<
action: :insert,
changes: %{
id: "some-unique-identifier",
name: "some-name",
image: "some-url",
variant_id: "some-unique-identifier",
quantity: 1,
price: Decimal.new("2.99")
},
errors: [],
data: #Pdex.DraftOrderCreationForm.Item<>,
valid?: true
>
]
},
errors: [],
data: #Pdex.DraftOrderCreationForm<>,
valid?: false
>
The schema for the parent and child items is the following (both are not persisted to the db)
defmodule Pdex.DraftOrderCreationForm do
import Ecto.Changeset
use Ecto.Schema
@primary_key false
embedded_schema do
field :order_id, :string
field :customer_id, :string
embeds_many :items, Item, on_replace: :delete do
@derive Jason.Encoder
field :name, :string
field :image, :string
field :variant_id, :string
field :quantity, :integer
field :price, :decimal
end
end
Shouldn’t the fact that an id is present be enough to render it in the markup ? Or should the id be both present AND the resource a persisted one ?
Your embedded schemas do not have primary keys and the inputs_for
needs to use the IDs of the association/embeds.
4 Likes