I have a controlled number input in a React app, and when I remove all the digits right of the decimal point, the decimal point itself is removed. So when I have 1.1, and remove the rightmost 1, it should leave 1.; but the point is also removed automatically, leaving 1, and the cursor is moved to the front.
For a minimal example, see this fiddle: https://jsfiddle.net/sashee/e00s7h9d/ . Just press backspace on the input to observe the behavior.
After some googling, I think the root of the problem is that 1. is treated as 1, and there is no way to extract the current value from the input.
Therefore, when I remove the rightmost 1, the following happens:
The change handler is called
The value is 1
React updates the value in the state to 1
The input now has the value of 1, instead of 1.
As I see, this is not a bug, but a weird outcome of the architecture. Are there any workarounds that use number inputs? Or should I fall back to regular text inputs?
Update:
It works fine in Firefox, but not in Chrome.
It turned out to be a bug in React itself, see this PR.
It is fixed from 15.5.4 onwards, see this fiddle:
<script src="https://unpkg.com/react#15.5.4/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/react-dom#15.5.4/dist/react-dom.js"></script>
Is there a reason why you would like to have that decimal in place when you delete the number proceeding the decimal point? This isn't so much as a React question as it is more a general HTML one. Like you mention, if you would like the decimal point to show when you are inputing a number, then you can change the type="number" to type="text".
Also, I'd like to point out that in your initial state, you are setting the value to a string, and then the string "1.1" is being coerced into the number 1.1. For consistency you should set the initial state to a number if your input is type="number" or keep the initial state as a string and change the input to type="text"
If you would like the number in the box to increment or decrement by 0.1 every time the up or down arrow are pressed, change the step to step="0.1".
The issue is that you're defining your input as type="number" but the value you're throwing into it a string. When the string "1." gets converted to a number, it loses the decimal value.
// Example of string "1." getting converted to a number
parseInt("1.", 10) // 1
How to fix:
As #Yo Wakita says in his answer, just use a string input. However! You can easily disallow non-numbers with a RegEx:
_onChange(e) {
// This will match all signed/unsigned floats
// Pattern credit: http://stackoverflow.com/a/16951568/2518231
// You'll probably want to store this as a default prop so that it isn't generated on every onChange
var regex = new RegExp(/^-?\d*\.?\d*$/);
if (regex.test(e.target.value) ) {
this.setState({val: e.target.value})
} else {
alert('Sorry, only numbers are allowed.');
}
},
Related
I have a state which has a field value as number which contains many decimals. I want to parse it to fixed(2).
But if I do so in the value of my input I have problems when typing a new value, and only accepts the first number. I can type 4 and gets 4.00 but I can't type 44 neither add decimals.
Is there a way to isolate the value which is displayed from the actual value?
I don't want to parse the value before because I would lost precision and my real value would change. The idea is just trimming my value which is displayed in the input only for visualization purpose.
<input
onChange={e=>setTakeUp(e.target.value)}
value={(+takeup).toFixed(2)} />
I'm a bit confused here..
I'm trying to create a field with number and binding it into ng-model, but when I input this value
10000000000000000000000
It gets me 1e+22 on the model result, how can I make it as number not this string when I input lot of 0 behind.
Hopefully somebody here giving me 10000000000000000000000 then it should returns 10000000000000000000000 on the ng-model.
https://codepen.io/anon/pen/NaxoXJ
Thank you
How can I make it as number not this string when I input lot of 0 behind.
It's not a string, it's a number displayed using the scientific notation. Javascript uses this notation for big numbers. For example, in JS, this king of statement is valid :
var i = 1e+22;
Instead of using {{test}} to display your value, call a function to format the number correctly (the result will be a string and not an number).
This post explains how to print a number wihout using the scientific notation.
Updated codepen
I have a <input type="number"></input> field and when I try to put in a decimal as the first character, it comes up as invalid (I have an ng-change firing).
.5 won't work, but 0.5 is valid. Is there something I can do about this?
Per the HTML spec, .5 is valid for <input type="number">.
So, you’re right, and the tool (browser? Angular?) that validation error’s originating from is wrong.
As far as how to deal with it—how to work around it—I don’t know what to suggest, but as someone who actually works on the specs for this stuff, I would like to ask you to please at least file a bug against whatever tool is (mis)performing the actual validation that’s causing you to see that message. If nobody takes time to report spec-conformance bugs like this (but instead everybody works around it by just putting, e.g., 0.5 to get past it), then the bugs never get fixed.
Anyway as far as evidence for my assertion that .5 is in fact valid: The HTML spec is pretty clear on this; see the section defining what a valid floating-point number is:
A string is a valid floating-point number if it consists of:
Optionally, a U+002D HYPHEN-MINUS character (-).
One or both of the following, in the given order:
A series of one or more ASCII digits.
Both of the following, in the given order:
A single U+002E FULL STOP character (.).
A series of one or more ASCII digits.
Optionally:
Either a U+0065 LATIN SMALL LETTER E character (e) or a U+0045 LATIN CAPITAL LETTER E character (E).
Optionally, a U+002D HYPHEN-MINUS character (-) or U+002B PLUS SIGN character (+).
A series of one or more ASCII digits.
Along with that evidence from the spec itself, here’s a record of other supporting evidence: There was in fact a time when the HTML spec didn’t allow .5 but instead required it to be written as 0.5; however, after a “Floating point numbers beginning with a dot should be valid and parsed correctly” bug was raised against the spec, the spec was subsequently changed (in 2011) to state what it currently states (that is, too allow, e.g., .5).
So, any tool that’s flagging .5 as an error likely has not been updated in this regard since 2011, and so it regardless is in need of its maintainer(s) to go back into their code & evaluate their code against the current spec requirements, to make sure they are conforming to the current spec.
I hope the above provides enough ammunition to use in raising a bug against the responsible tool.
If you want all the input numbers to be valid then you can set in your input field step to "any". It works all integers and decimals numbers. Like -
<input type="number" step="any" />
can any one explain why(how) the xtype: numberfield value is going to auto correct(change) if am providing more than a 16 digits value.
For Example:
22222222222222222 is changed to 22222222222222224
222222222222222222 is changed to 222222222222222200
2222222222222222222 is changed to 2222222222222222300
22222222222222222222 is changed to 22222222222222220000
222222222222222222222 is changed to 222222222222222230000
2222222222222222222222 is changed to 2.2222222222222222e+21
22222222222222222222222 is changed to 2.2222222222222223e+22
Which results in my page after rendering as shown below when get the value through in my component jsp page
NumberFieldTestValue:<%= properties.get("numberfieldname","") %>
Resulting as below
NumberFieldTestValue: 2.2222222222222223e+22
The problem
This behavior is caused by the fact that the dialog behavior is implemented in JavaScript. The numbers you're having problems with cannot be represented in it.
The language conforms to the ECMASCRIPT 5.1 specification.
To quote the Number type description
all the positive and negative integers whose magnitude is no greater
than 2^53 are representable in the Number type
The base 2 logarithm of 2222222222222222222222 is about 70, which means the number exceeds the maximum value. Hence your problems.
All in all, if you check your examples in a plain JS console in a browser, the same behavior will be displayed so this is not really a CQ problem.
Solution 1 - use a different type
To avoid this, you could potentially use xtype="textfield" and validate it against a regular expression to see if it consists of numbers only. Then you'd have to make sure to use a type capable of holding such numbers at the backend (like BigInteger).
The field could look like this:
<numberOfSandGrains
jcr:primaryType="cq:Widget"
fieldLabel="Number of grains of sand at the beach"
name="./grainsCount"
regex="/\d+/"
regexText="Please enter a numeric value."
xtype="textfield"/>
Solution 2 - change scale
Another option is to change the logic behind the configuration and use some different units if applicable. For instance, if the value 2222222222222222222222 is a number of grams (weight of an object/substance), it makes perfect sense to read it in metric tons instead (at least in many cases). The author could probably do without entering such humongous numbers.
You'll need to be extra-careful if you go this way.
I have a mask setup on a date field using the angular-ui masks module like so:
<input type="text"
id="date"
ng-model="transaction.date"
ui-mask="99/99/9999" />
If I have 30/05/2013 in the field and want to change that to 10/05/2013 by simply putting a '1' at the start it pushes all the characters over so it becomes 13/00/5201.
Is there way to force ui-mask to overwrite the character insted of inserting it? (This would save someone from hitting 'delete' then the character.
Example: http://jsfiddle.net/5NbD7/
If you type '30' at the front of my example you will end up with 30/01/0120 I would rather it override the characters and produce 30/01/2010
I don't know it there is an easier way, but you try the following :
You will need to download mask.js, unminified, from source and link it in your html, if you haven't already done so.
https://rawgithub.com/angular-ui/ui-utils/master/modules/mask/mask.js
Then you will need to modify the source code of mask.js like this (seach for the comment //Update Values and put this code below) :
...
// Update values
if (oldValueUnmasked !== "" && oldValueUnmasked!==valUnmasked && !isDeletion) {
var charIndex = maskCaretMap.indexOf(caretPos);
if (charIndex === -1) {
charIndex = maskCaretMap.indexOf(caretPos+1);
}
valUnmasked=valUnmasked.substr(0,charIndex).concat(oldValueUnmasked.substr(charIndex,valUnmasked.length));
}
...
Now, before updating the value, mask will do a concatenation of the characters in the old value and those in the new value, depending on the position of the cursor (caret).
It's by no means an ironproof solution, but it should give you an idea of where to look if you want to customise the input more or check that this change does not break anything else.
Fiddle:
http://jsfiddle.net/CALvj/
I think that the way typed characters are inserted or overwrite input text depends on the keyboard current insert mode. Users can simply change the default pressing the Ins key.
The only way to change it from code would be forcing an Ins key press but this isn't allowed in Javascript.