I’m using Elixir Money to handle my money integers. I have a form for creating a %Product{} which has a column defined as field :price, Money.Ecto.Amount.Type in the schema and add :price, :integer in the migration for postgres. Creating a new product is fine, but I’m encountering problems when I try to edit and update.
The Money library returns a struct for the field (ie %Product{:price => %Money{amount: 500, currency: :USD}}) so when you render the products/edit page, nothing shows up in the :price field and, even worse, if you submit the form without entering anything into the field it updates the column to null meaning you have to remember what it currently is, press the edit button to get to the form and then type the value into the field before you forget.
Before I start creating alternate changesets, routes and/or forms, is there any way to get the :price number_input field to interpret what is returned from the schema and render it normally on the edit form, keeping in mind that the /new route also renders the same form.html.eex?
I think I just needed to type out my problem to get the gears spinning, here’s what I’ve learned:
The controller under the edit/2 function (assuming you’re using phoenix generators) sends you product: product in the render call. I was confused about how the form knew where to get the values from since there is no explicit @product variable being used anywhere in the form, phoenix seems to take care of that for you as long as you declare the corresponding field name.
input_value(f, :price) is basically doing what you did with @product.price, but using the phoenix_html form handling and without additional assigns besides what you passed to the form (e.g. @changeset).
I don’t understand how to let users choice currency. I add field like
<%= number_input p, :price, value: input_value(p, :price) %>
but i also need another input with currency (like USD, EUR and so on)
how to do it?
…["price"]["amount"] for the name of the amount field and …["price"]["currency"] for the name of the currency field should work with the ecto types of ex_money.
My team and I stumbled upon this thread in 2023 since we’re looking into using Elixir/Phoenix for a product rewrite, and were looking into using Money for handling currency. AFAIU, the auto-generated code for core component stuff has changed since 2019, but this is what ended up working for us:
The part that wasn’t immediately intuitive was whether there was a better way to just pass Money.to_decimal as a “type-cast” somewhere to the component, or whether it should just be passed in as the value to the <input>. Realistically, it’d probably make more sense to just extend the input core component to have a “currency” variant where the assign_new call has the Money.to_decimal call directly inside it.