Sanjibukai

Sanjibukai

Hello all,

I have a form with one price input field.
In order to follow industry standards (and for learning purpose) I’m using Money.
Currently I’m only dealing with only one currency (EUR), so I’m not into currency conversions etc.
I intended to use it only for the ease of formatting purpose as well as for the precision handling.

That being said, outputting a Money field is nice when displaying the value.
But I’m struggling for getting the value from a form.
At first I was not sure if I should use a text input field or an number input field.
It turns out that by the Money type is considered as a string.
But I had to disable the currency display since I already have a custom css displaying the currency in a styled way. So I’m basically using only the amount part.

But in that case, I wonder that I can simply go with a number field with the benefit to display a dedicated number keyboard in mobile.
The problem is that if I’m using a phone that has an English local, I cannot use commas but only dots as decimal separator.
And in this case if I put 12.34 I am ending up with 1234.00

When I’m using a text field it correctly handles the comma but not the dot.

Is it possible to set both the comma and the dot as the decimal separator?

How do you guys handle those pesky formatting problems?

Thanks for any comments..

Showing Posts 1 to 10

kip

kip

ex_cldr Core Team

ex_money (I am the author) can parse input numbers in any of its known locales using the locale-specific separators. Including parsing amounts with the currency sign since, as you point out, the display output most commonly uses that. Here are some example that might help:

# Default to EUR since thats the default currency for Germany
iex> Money.parse "10.000,43", locale: "de"                
#Money<:EUR, 10000.43>

# Parse an accounting amount
iex> Money.parse "(10.000,43)", locale: "de"    
#Money<:EUR, -10000.43>

# With a symbol
iex> Money.parse "€10.000,43", locale: "de" 
#Money<:EUR, 10000.43>

# Currency is specified
iex> Money.parse "CHF 10.000,43", locale: "de"
#Money<:CHF, 10000.43>
Sanjibukai

Sanjibukai OP

Thanks for taking the time to answer!
In another project I was using your package (not the latest version).
But with this new project I tried with your latest version but got some dependency errors (with ex_money_sql).
So I’m using the other package.. But I guess that regarding this part they work the same, right?

However, my problem is more about the fact that if I want to grab a decimal value from a number input field in the HTLM, the locale is not taken into account.

I mean, the browser validation only allows the decimal symbol of the user’s locale. For example in my devices (phone or computer) I have English locale, so I cannot input the comma in the input field.

I can only use the dot as the decimal separator. But then I don’t know why, I receive the value as if there was no decimal separator.

I don’t have any issue when I use parse in controllers (or in IEx).
But in my case I defined the type in the schema and the changeset as well as the default locale, so everything just happens. But unfortunately, not the way I want when using a number_input field.
I wonder if I should divide the received value by 100, if so where?

kip

kip

ex_cldr Core Team

Sorry to hear you has an issue with ex_momey_sql. Please do raise an issue on github or DM me. I have had no issues reported so I want to quash this asap.

I believe the number input field in most (all?) browsers don’t allow the input of the separator, only the decimal point that is in the currently set locale for the browser. Most issues I’ve seen come from the server rendering a formatted money amount that includes currency symbols and/or separators that cannot then be edited correctly because of the restrictions on a number field.

Sanjibukai

Sanjibukai OP

No problem! It seems to be a version bumping issue..
If I look here ex_money_sql | Hex it seems that ex_money_sql is wanting ex_money 5.0 instead of 5.2.

My bad, when I was saying decimal separator, I was talking about the decimal point separator.

Indeed, if we keep the field as a number field, the browser only expect a string with bare numbers (no currency symbols) so I can use the the amount part of the Money.

But still, if I put using anEnglish locale 9.99 (meaning ~10), the dot is not taken into account and I got in the changeset 999,00 (so ~ around 1000).

I’m still struggling to find how to do that simple task..

kip

kip

ex_cldr Core Team

ex_money_sql indicates that it will work with ex_money from 5.0 and hex will retrieve the latest version which matches which will be 5.2.

Can you show the HTML that is generated for the input field (or the template that generates it)?

Sanjibukai

Sanjibukai OP

Hello @kip,

Thank you for your last answer.
But because of the pandemic I had to stop working in that project.
Meanwhile, I switched back to a regular text_input so I don’t get that decimal point error depending on if it’s a dot . or a comma ,.

However, I’m just facing another error related to the display of the currency symbol..

Let’s say I have the following very simple schema (where it’s assumed that both fields are required):

schema "products" do
  field :name, :string
  field :price, Money.Ecto.Composite.Type
end

I also have the following Cldr config:

defmodule MyApp.Cldr do
  use Cldr,
    locales: ["fr"],
    default_locale: "fr",
    providers: [Cldr.Number, Money]
end

Now let’s consider that I have the following HTML form:

<%= form_for @changeset, ..., fn f -> %>
  <%= text_input f, :name, required: true %>
  <%= text_input f, :price, required: true %>
...
<% end %>

Regardless of if I type 10, 10,0 or 10.0 everything is working like a charm and I will get the correct “value” displayed as 10,00 €.

However, if I type an amount in the price but not in the name, since it’s required I’ll get a changeset error and the form will be displayed again.
The problem, is that the price amount will be displayed as formatted like 10,00 €.
And if I put a name and want to submit again, the name will pass this time, but not the price amount!

ex_money doesn’t accept its own formatted string.
I get the following error: The currency \" €\" is unknown or not supported.

What I am missing?
I’m sure I’m missing something because those simple very common tasks of manipulating money in forms shouldn’t be that complicated.

I guess I can handle the value to display in the form fields manually with the value: attribute, but this seems very overly complicated..

Thank you for any thoughts..

kip

kip

ex_cldr Core Team

@Sanjibukai, any chance you have a minimal reproducible case? I’m not seeing the parsing issue. For example:

iex> Money.parse "10,00 €", locale: "fr"         
#Money<:EUR, 10.00>

# With "fr" as the default locale
iex> Money.parse "10,00 €"              
#Money<:EUR, 10.00>

Perhaps check you are on ex_money version 5.3.0 (which is the latest version)? How are you validating the price in your changeset?

Sanjibukai

Sanjibukai OP

Hi @kip and thanks for the quick reply!

I’m getting a no matching error when I try to get the version 5.3.0. It seems that the latest version is 5.2.1 (which is also what mix shows in the error as well as what’s displayed in hex.pm and in your github repo too).

Anyway, I tried in IEx (while having the server running thanks to iex -S mix phx.server), and indeed it’s working in IEx..
Both commands (with and without the additional locale: "fr" parameter) are working in IEx..
But still not working in my app.

I noticed that despite having a single locale (“fr”) defined in the MyApp.Cldr module, the following message showed up when compiling:

Generating MyApp.Cldr for 4 locales named ["en", "en-001", "fr", "root"] with a default locale named "fr"

I don’t think the other locales might interfere since it’s stated that the default one is “fr”.
But might it be a problem?
While, I’m here, what is “en-001” and “root” and where they came from?

Also, regarding the validation, I’m doing nothing special. I’m casting and validating as usual like so:

product
|> cast(attrs, [:name, :price])
|> validate_required([:name, :price])

Thank you for any direction..

Edit:
The validation error I got is the following:

#Ecto.Changeset<
  action: nil,
  changes: %{name: "ABC"},
  errors: [
    price: {"The currency \" €\" is unknown or not supported",
     [type: Money.Ecto.Composite.Type, validation: :cast]}
  ],
  data: #MyApp.Product<>,
  valid?: false
>

Edit 2:
If I type 10, I receive back the following string: 10,00 €..
Something weird that’s happening is that, if I delete the space like so 10,00€, or even weirder, if I select that space (with highlighting with the mouse) and put back a space again (so apparently nothing changes), the error disappear…
:thinking:

Sanjibukai

Sanjibukai OP

Hi @kip,
I think I found the culprit!
I paste that space in a unicode decoder, and indeed it’s not a regular space (U+20) but rather a non breaking space (U+A0).
This is a good thing to not have the symbol wrapping around, but it’s not being parsed correctly.

When I try the same IEx example as above but inserting that no-break space I got the error again!
I’ll try to check in the code base to see how you are parsing the string and maybe adding other white spaces to the literal regular spaces..

kip

kip

ex_cldr Core Team

Good catch, confirmed! Fix coming in about 30 minutes.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews