-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: Backspace in input type="number" behaves badly in Blink #7253
Comments
😢 Thanks for filing. I confirmed 15.2.1 is still broken too. Most likely more fallout from #6406. |
Number inputs are broken in React, due to #6556, which was filed before #6406 was merged. You're going to see the same problem with email inputs (as per #6368, which is basically the same issue, again filed before #6406 was merged). It is entirely possible that #6406 exposes that bug for defaultValue, but the bug was always there in the React core and was always visible for controlled inputs. This has been broken in React for as long as I can remember:
A workaround is to set |
@jimfb Understood, it's very frustrating that there is no way to get the raw value out of an |
@STRML That's because Firefox doesn't fire an onChange if the input's value is invalid. It's an interesting way of sidestepping the issue in the common case, since the onChange behavior is presumably undefined when the input is in an illegal state. |
Based on these two codepens, this bug was introduced in 15.2.0. 15.1.0: http://codepen.io/stephenjwatkins/pen/GqxGWJ [works] |
Wow, did Chorme just release an update? I'm 98% positive that codepen would not have worked a week or two ago. It looks like Chrome will now retain the "." when the user does a The fiddles in #6556 are now all behaving in a "nicer" way now. Looks like the ball is back in our court. How much you want to bet that Chrome fixed this because of React? |
Still broken in 52.0.2743.82 (64-bit), are you seeing this working with 15.2.0? |
What is still broken? I'm talking about the fiddles in #6556. Do those still look broken to you? |
Confirmed for me on: Specifically, it looks like To reproduce: <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chrome Backspace Issue</title>
</head>
<body>
<div id="container"></div>
<script src="../../build/react.js"></script>
<script src="../../build/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
<script type="text/babel">
var NumberInput = React.createClass({
render: function() {
return <input type="number" defaultValue={ this.props.defaultValue } />;
}
});
ReactDOM.render(
<NumberInput defaultValue={3.14} />,
document.getElementById('container')
);
</script>
</body>
</html> If you backspace to clear the Do I have this right? And should uncontrolled inputs even assign values to begin with? |
Ahhhh interesting. Maybe I was just in the dark, but assigning Check out this Codepen: http://codepen.io/nhunzaker/pen/zBaokp This covers uncontrolled inputs, but controlled inputs follow different rules and seem to rely on I've sent out a PR here: |
@jimfb You mentioned:
This seems ideal to me: to trade off limiting change exposure for the sake of stable inputs. Is there any interest in moving towards this? |
@nhunzaker Sorry, I'm on hackamonth, haven't really been following these threads super closely. We can't mimic Firefox's behavior, because we can differentiate between the user clearing their text input and an invalid value, AFAIK. However, I think Chrome fixed their inputs to work correctly, so this class of issues is now fixable. We would almost certainly be interested in a PR. I'll pass this off to @zpao @spicyj and @gaearon. |
No worries, sounds fun! If there's a quick reference point, could you reveal more about the Chrome fix? What was actually broken? |
@nhunzaker I don't know any quick reference points other than #6556, but the basic problem was that we couldn't get the actual input value (as entered by the user) when the input was in an invalid state (eg. as the user is typing "3.14", there is an illegal intermediate state "3.") and setting the last known legal value would remove the decimal point. Firefox's fix was to not fire onInput for illegal states, Chrome's fix was to not remove the decimal if the value is approximately the same ("3" instead of "3."). You'll need to do a little digging to figure out the exact behaviors of the various browsers and figure out what a good fix would look like. I don't know the answer off the top of my head, but it looks like things are now sufficiently fixed on the browser's end, so this should be fixable now in React. FWIW, it may be worth tracking keystrokes and cursor events and paste events, and maintain a perfect shadow state. Since we don't have to deal with non-numeric-ish characters, we don't need to worry about foreign languages (which is where all the input edge cases come from). I think this would allow us to simulate what the browser would do (allow us to know what value is actually in the text box) and sidestep all the weirdness of the type=number spec. Anyway, I'll let you guys figure that out. |
Okay! So it looks like the issue here is that There is some logic in Unfortunately the new value has already been assigned. So my first quick hack was to add an exception for value assignment so that it never sets the value attribute if it hasn't changed: master...nhunzaker:nh-chrome-backspace I don't really know why this works. I didn't think |
Here's a quick GIF: Now it looks like I was dumb and pushed this update to the uncontrolled input fix I sent out here: I'll work on getting those tests to pass until we can figure out what to do. |
Okay. I've polished up #7359. It fixes all issues with uncontrolled and controlled inputs that I have encountered. I'll put in some extra time to manually test this tomorrow. I'm still struggling to add automated test coverage for these quirks. |
Here are the cases that I'm covering, using the following code as a test case: https://gist.github.com/nhunzaker/923efbaddca16ae2384b547555157f61 Do not drop off the decimal place when backspacingThis happens because React sees "3." and tries to compare it against "3". Since it's a string comparison, these are always different. before: after: Do not clear on bad inputThis is sort of correct. This works because I'm doing before: after: Do not "expand" valuesThis happens because before: after: Pretty neat! Anything else I've missed? |
I would suggest going one of two ways:
|
What is the current state of this issue? |
I have an outstanding PR here:
Update: Sorry. Looks like something on CI. Upstreamed anyway. |
Spam again... Seen a lot of this lately On Nov 20, 2016 1:27 PM, "qagiux" [email protected] wrote:
|
What's the state of this issue? We are still encountering this on v15.4.2 |
This should be addressed in 15.5, now that we've merged the number input PR: I'll leave this ticket open, I don't know what the protocol is on closing tickets before a release with a fix has been published. |
cc @aweary I just realized I can't close this :( |
Fixed! https://jsfiddle.net/09Lxxzn9/1/ Thanks for your hard work @nhunzaker. |
This appears to have been introduced in a new Chrome version, but I can't find any reference to where.
Affected/Tested Browsers (OS X):
Unaffected Browsers:
Backspacing in an input element with
value
ordefaultValue
set causes some very odd behavior. Once a decimal point is gone, it can't easily be re-added.Example:
In this example, I simply backspaced twice. On the second backspace, when I expect
3.
to be showing, the input instead reads3
and the cursor has moved to the beginning. The next two jumps are my attempts to add another decimal point.Fiddle: https://jsfiddle.net/kmqz6kw8/
Tested with React 15.2.
Notes: This only occurs when
value
ordefaultValue
is set. If neither is set, the input behaves properly. We are currently working around this issue by (unfortunately) setting the input value oncomponentDidMount
via a ref.The text was updated successfully, but these errors were encountered: