Is it able to change the behavior of to_string for `Money.Ecto.Composite.Type` ?
Daniel-Xu opened this issue · comments
Daniel, thanks for the report. Can you send me the HTML of the relevant part? What are you trying to achieve? What output are you looking for?
BTW, the actual number formatting is done by Cldr.Number.to_string/3
so you can check the options available there too.
I'm using live view and live validation, the html is normal number_input
<%= label f, :single_price, "", class: "uppercase md:text-sm text-xs text-gray-500 text-light font-semibold" %>
<%= number_input f, :single_price, autocomplete: "off">
from the changeset, the single_price is type Money
, this will be serialized into $333.00
. However, the dom differ can't parse this format.
#Ecto.Changeset<
action: :validate,
changes: %{
single_price: Money.new(:USD, "333"),
}
From the error in console, I'm guessing the to_string result of Money.Ecto.Composite.Type
can't work well with live_view dom diff.
What I want to achieve is to be able to change the output of to_string
for Money.Ecto.Composite.Type
to 333
instead of $333
. Hope it's clear.
I was able to solve this by:
- change
number_input
intotext_input
- using
currency_symbol: ""
(this is not necessary, but it makes the field look like a number field)
Daniel, the error is probably because you are using a number input field and providing it with a currency string that includes non-digit input.
This has nothing to do with Money.Ecto.Composite.Type
. The only relevant type is Money.t which combines a currency code and a decimal amount.
I believe you have a couple of choices:
-
Don't use a number input type, use a text input type. And then use Money.parse/2 in your controller to parse it back into a
Money.t
. This allows you quite a flexible input mechanism but it does mean you don't get any benefit from browser-side number formatting and validation. You do get a "round trip" experience though in which the output string can be parsed back into aMoney.t
if you need. -
Just format the currency amount as a number and pass the number into the DOM. You can get the amount with Money.to_decimal/1 and then format it any way you want (Cldr.Number.to_string/3 or Decimal.to_string/2) for example.
The highest priority for ex_money
is to preserve the integrity of a money-with-currency type and therefore I have no plan to modify Money.to_string/2
from its current behaviour.
Daniel, glad you found a good way forward. I know that there needs to be a better way to format and enter currency amounts in HTML and its on my "to do" list. Thanks for letting me know what you did so I can share that if asked again.