I've seen too many examples, but none have convinced me of what I really want and the best practice to do this.
I have my code as follows:
const nf = new Intl.NumberFormat("es-MX");
let anualidad = 1200;
this.model.enero = nf.format(anualidad);
output: 1200
My problem is that it doesn't put the comma in 1,200
; I'm not saying it doesn't work, because if I put another zero it adds the comma like this 12,000
.
I already set the language to MX .
How can I do this in the best way? since there are too many calculations that have to be done in this way.
I did a fairly exhaustive investigation of the subject, and I will base my answer on the result obtained in it.
First of all, although the possibility of using another system of
locale
(for exampleen-US
) has already been discussed, that doesn't fully answer the question.Clearly you want to convert from a type
Number
to a typeString
, but have it represent a figure with a local format fores-MX
(Mexican Spanish).If we make use of the method
toLocaleString()
, or the methodNumberFormat
of the objectIntl
, we obtain the following result:It clearly doesn't put the decimal point if the number of digits for the thousands group is less than 2.
SOLUTION
One way to solve this problem (I say problem, although it is not a
bug
language problem, but a standardization decision) is to manually convert the number, since the standard is not giving us the desired result.In your question you indicate that you have seen many forms, but none of them convinces you. The truth is that for tastes, colors .
This is my proposal, but I understand that it can be done in many other ways.
We create our own format function, supported by the Regular Expression engine of the JavaScript engine.
We will use the following regular expression to format our number in the desired locale:
In this regular expression, a
positive lookahead
(?=
) is made, looking for one or several (+
) groups of 3 digits ((\d{3})+
), if there are any, it is returnedmatch
together with the values grouped in 3. Then, anegative lookahead
((?!)
) is made to discard any digit that is not grouped by the first capture group (in this case 1 or 2 digits). You can read more about itlookahead
in Regex Lookahead .We will use the method of the String
replace
object , which accepts a regular expression (which we already have) and a type parameter with the following format:String
Thus, our parameter will be the following:
Where
$1
represents the first argument: our regular expression, and,
is the separating thousands symbol that we will use for this case.Finally, we must decide whether we always use this method to replace the method
toLocaleString()
or we can combine both.Suppose we are going to always use this method for any valid numeric value:
Clearly we have a serious problem, as there are invalid results.
The problem is that the replacement is done without taking into account that the decimal places should not be part of the replacement.
To solve this problem we have some options, and as I said before: for tastes, the colors .
Since a Javascript number can only contain one character
.
or none, we'll use this to apply our function only to the integer part of the number.We're going to separate the integer part from the decimal part, apply the format to the integer part, and then concatenate everything back into a
String
.With this we have a function that helps us convert numbers to their string representation in local Mexico format (decimal point and commas for thousands separation).
Applying this to your code, you could have:
Modifying this method a bit we can do it for any numerical representation system we want.
Why
toLocaleString()
orFormatNumber()
not put the thousands symbol for figures between 1000 and 9999?It's a decision made (I don't know why) by the Unicode Standards Organization . In particular by the CLDR ( C ommon L ocale D ata R repository ) project.
The standard establishes, among other things, the numeric format pattern . And within that pattern, there is a property or attribute called
minimumGroupingDigits
, which sets the number of minimum digits in a group to use the thousands separator.The fact is that this value is equal to 2 (as can be seen in the CLDR Survey Tool ) in all numerical formats belonging to the specification
es
(which includes Mexico).Because of this, the aforementioned methods will always return 4-digit integers with no thousands separator.
I hope this clears your doubt and helps you solve the problem.
According to the documentation of the IETF labels, the code for Latin America and the Caribbean is
es-419
and makes a lot of sense since in Argentina, Colombia or Mexico the expression is the same.You can check it here
I've been doing some tests but unfortunately that tag is not working. What if is that, if you don't pass anything to the constructor it takes the format you are looking for.
I hope you can guide
EDIT
Doing some tests I used an Object tracker
Intl.NumberFormat()
and found that theIntl.NumberFormat().resolvedOptions()
Has an object of this typeThis may change depending on the browser being used. I have passed the tag to the constructor
en-MX
because sometimes it works (I have seen it in other projects) or Voilá! it worked.I recommend the following:
It doesn't work with Argentina es-AR
Using the German format, it gives the required result: