Multiple places in my application, I have changesets where one or multiple of the fields represents an amount. In the field in the form, they should be able to write the amount as a string
e.g. “12”, “,3”, “1 234,5” etc. In the database, it should be stored as in cents (so *10) and as :integer
, so “1200”, “30” and “123450”.
The problem is when to handle the transformation from string to integer and in cents. Currently I am seeing two options, but not sure if either of them are good or if there are better ways to do it.
-
Using AlpineJs and having a hidden field, where I transform the inputv-alue to an integer that is stored in the hidden field, and then used in the changeset. The problem here is that I have some validations in the changeset and some outside of it, and would like to not have to involve AlpineJs.
-
Having a virtual field for each amount-field, and where the transformation from string to integer and validation is done in the changeset.
The problem here is that I would need one virtual field for each amount field, which would be more messy, I feel.
I am using Liveview, so each the a field is changed, the params from the forms are given to the changeset. Hence it is important to not transform a value that is already changed again. For example if typing “12”, it should be transformed to “1200” to be stored in the database upon insert/update. But if another field is changed, it should not be transformed again to “120000”.
I’m using Elixir 1.14, Phoenix 1.7.0 and Phoenix Liveview 0.18.18.
Anyone who have thoughts about other ways to do it?