Skip to content
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

Controlled number input doesn't handle e, - and . properly #6556

Closed
dhruska opened this issue Apr 20, 2016 · 18 comments
Closed

Controlled number input doesn't handle e, - and . properly #6556

dhruska opened this issue Apr 20, 2016 · 18 comments

Comments

@dhruska
Copy link

dhruska commented Apr 20, 2016

A controlled number input, without a corresponding setState function, still allows e, - and . to be entered (and numbers can be inputted afterwards). I could be incorrect but I don't believe this is the desired behavior.

Here's a JSFiddle demonstrating the issue.

@jimfb
Copy link
Contributor

jimfb commented Apr 20, 2016

Sounds like a bug, probably a good first one.

@zpao
Copy link
Member

zpao commented Apr 20, 2016

It's probably not a "good first bug" (it will surely involve at least looking at our event system, which is anything but good for a first dive into the code). But people are welcome to try :)

@jimfb
Copy link
Contributor

jimfb commented Apr 20, 2016

Yeah, I was torn on labeling this one. We need a "good third bug" label :).

The reason I thought it might be a reasonable first one is that the code from controlled text inputs can probably be copy-pasted here nearly verbatim. In fact, I'm a little surprised it doesn't already follow the same code path.

@zpao
Copy link
Member

zpao commented Apr 20, 2016

I'm pretty sure that typing in a <input type="number"> doesn't fire the same events (or only fires them for some interactions) so we just don't even know anything is happening. Otherwise I'm mostly sure the we don't differentiate between text and number types so we're already running the same code.

@syranide
Copy link
Contributor

I'm pretty sure this is just another case of these special inputs not playing well with being controlled, -e. are all part of valid numbers but only specific combinations actually translate to valid numbers. If the content does not translate to a valid number then the reported value is '' and it acts as if nothing has changed, AFAIK there is no way around this, at all.

@jimfb
Copy link
Contributor

jimfb commented Apr 21, 2016

Yep, @syranide is correct. https://jsfiddle.net/1tscfoLf/

Not sure if there is anything we can do about this at the moment, short of writing our own handlers based on cursor position and keystrokes. Maybe that's what we need to do. (or request revisions from W3C, but that's a longer term thing)

@ccorcos
Copy link

ccorcos commented Sep 19, 2016

I found this bug too!

https://jsfiddle.net/tmbbau6a/

Any ideas for work arounds?

@rhythnic
Copy link

rhythnic commented Mar 7, 2017

This bug happens when using decimal in an input with type number. When adding a decimal to a number, there is no problem. When removing decimal places from a number, after removing the first decimal place, just prior to removing the decimal, the decimal disappears and the cursor jumps to the beginning of the input.

For instance, if the value is 30, and I type '.', the value in the event is '30', and event though the input is controlled, the '.' is allowed to remain in the input.

If the value is 30.1, and I delete '1', the value in the event is '30', but the decimal disappears and the cursor jumps to the start.

@gaearon
Copy link
Collaborator

gaearon commented Mar 7, 2017

See #7359

@nhunzaker
Copy link
Contributor

This should be addressed in 15.5, now that we've merged the number input PR:
#7359 (comment)

@aweary aweary closed this as completed Mar 27, 2017
@dhruska
Copy link
Author

dhruska commented Mar 27, 2017

Wow, what a thread. Thank you!

@johnjesse
Copy link

@nhunzaker I'm sorry, but I don't think this issue has been addressed, you can still quite clearly type - . and e into a controlled number input and have them appear even though I have not updated the value see
https://codepen.io/johnjwood/pen/GvWRzp?editors=1111, and try typing "-" or "." or "e",
they shouldn't appear as I'm not updating the value, and yet they do

I think this is because the browser (I'm on Chrome Version 60.0.3112.90 64-bit) doens't seem to be firing an onChange event when the value is invalid, I'm still a bit hazy as to whether that is down to the browser or react.

Either way this is still an issue and I suggest it gets re-opened

@nhunzaker
Copy link
Contributor

nhunzaker commented Aug 7, 2017

It looks like this happens because Chrome reports the value as an empty string:
https://codepen.io/nhunzaker/pen/mMWdNV?editors=0011

So React sees that the value hasn't changed, so it doesn't assign the value property. Unfortunately React has to avoid touching input.value if the value is the same to avoid input validations that cause nasty side-effects like dropping decimal places and expanding things like 1e2 into 100.

I don't know what to do here. Is this a bug?

cc @jquense @aweary for discussion.

@nhunzaker nhunzaker reopened this Aug 7, 2017
@aweary
Copy link
Contributor

aweary commented Aug 7, 2017

At this point, I almost think this is an acceptable concession with controlled inputs. As far as I can tell, we'd have to introduce a lot more logic using key events to manually determine if we need to remove these numerical characters.

The decimal dropping bug was a huge pain, so we need to avoid introducing any more changes that may compromise that fix.

@aweary
Copy link
Contributor

aweary commented Sep 15, 2017

Coming back to this, I still think accepting this as a concession is our best choice. We are limited by the data/events that the DOM will provide us, and in this case, it's not enough to implement the desired behavior without hacky solutions.

If you absolutely need to ensure that invalid values cannot be entered you can use a text input and manually validate the value in the onChange handler.

With that said, I think it's best to close this and possibly document the behavior if we need to.

What do you think @nhunzaker @jquense?

@jquense
Copy link
Contributor

jquense commented Sep 16, 2017

I agree yeah. This is an endless rabbit hole and I think the line should be drawn somewhere. Tbh the only real "correct" way to handle each edge case is to be culture aware and i18n adjacent.

@nhunzaker
Copy link
Contributor

I agree. @jquense is spot on too. I think, to do this right, we'd need spot on keystroke detection for at least number inputs, and that would have to work with every language.

This is an extremely hard problem, but we should the design challenges if we move forward with removing the value attribute syncing (#10150)

@JimmayVV
Copy link

JimmayVV commented Aug 2, 2018

FWIW I should mention, using tel as the input type rather than number allows many of the same benefits number brings, without as many (if any) of the drawbacks illustrated above.

Using tel still allows mobile phones to display a number pad input, and it's a little closer to semantic 'truth' than 'text', but obviously still not ideal.

It's the way I overcome this in my usage: TwilightCoders/card-games#13 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests