Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

input[type="number"] is valid when not a number is entered in Chrome #2144

Closed
4vanger opened this issue Mar 12, 2013 · 16 comments
Closed

input[type="number"] is valid when not a number is entered in Chrome #2144

4vanger opened this issue Mar 12, 2013 · 16 comments

Comments

@4vanger
Copy link

4vanger commented Mar 12, 2013

When entering invalid data into second field in Chrome - second is marked as pristine and valid which is incorrect.
Possible Chrome bug - parser from numberInputType is not invoked when typing non-numerics in Chrome

<input type="text" ng-model="test">
<input type="number" ng-model="test">
{{test}}

live example: http://plnkr.co/edit/fULfvq?p=preview

@groner
Copy link
Contributor

groner commented Mar 12, 2013

Somebody raised this issue on the list recently.
https://groups.google.com/d/topic/angular/pRc5pu3bWQ0/discussion

From http://www.w3.org/TR/html5/forms.html#number-state-(type=number)

User agents must not allow the user to set the value to a non-empty string that is not a valid floating-point number.

and

If the value of the element is not a valid floating-point number, then set it to the empty string instead.

If this problem only occurs when the browser is doing validation and the validation it's doing is the validation we want, it makes sense for the input directive to just observe the validity state of the DOM element.

@jglinsek
Copy link

I ran into this today as well. Actually, Firefox, Chrome and IE10 each handle this scenario (entering a non-number into a number input) differently which makes it a mess.

  • Firefox seems to handle it the way I would expect (or at least the way I want it to be handled).
  • Chrome, as noted, treats it as valid all the time.
  • And IE10 treats it as valid if there are no numbers in the input but NOT valid if there are some numbers and some letters.

Here is a plunker I put together based off the plunker in the Angular docs:
http://plnkr.co/SLnME6zXm653dLPHmjSr

@thatmarvin
Copy link

This was definitely not expected. I too was wondering why "asdf" was treated as a valid numeric input in Chrome.

@kevin1024
Copy link

Just ran into this today myself. If this isn't a bug, at least a note in the documentation would be nice.

@joakimbeng
Copy link

I ran into this as well, and noticed that the validation works when the required attribute is added to the input field, e.g:

<input type="number" ng-model="myNumber" required />

To me it feels like an Angular bug, because it doesn't add the ng-invalid class to the field without the required attribute.

Edit I've now tried with Firefox and there it works without the required attribute, so maybe it's an Chrome bug after all...

@kevin1024
Copy link

@joakimbeng see the comment from @jglinsek - Firefox handles the validation as expected. I think the difference is that Chrome doesn't expose the value at all when the field is filled out with something other than a number, but Firefox does.

@owenmead
Copy link

Also ran into this issue today. Firefox works as I expect. Chrome... not so much.

Issue is that when a non-number is entered into a number field in Chrome, it always returns an empty string from input.value

As @groner has pointed out, that is what the spec says to do. Although technically Chrome also shouldn't allow the input field to contain non-valid data. Pressing 'B' shouldn't produce a 'B' in the input field which would avoid this whole issue.

So because non-valid input always returns empty string, the listener function in textInputType is constantly comparing empty string to empty string, and thus never calling $apply which triggers the parsing etc. This is why the number error is never being raised, since it's an empty string, which is perfectly valid.

I'm happy to contribute a patch to try to solve this, but would love to get some general direction from core Angular developers as to the general strategy I should use to tackle this.

@michaelhunziker
Copy link

Hey guys!

Any news on this one?

I'm currently using Kai's solution posted here:
https://groups.google.com/forum/#!topic/angular/pRc5pu3bWQ0/discussion

Is this really the solution to this issue?

@owenmead
Copy link

owenmead commented Jul 4, 2013

As far as I know things haven't progressed at all with this. Still an issue with Chrome. Kai's works. You could also create a simple number type directive yourself that follows the spec and use that.

@caitp
Copy link
Contributor

caitp commented Oct 5, 2013

They said in that google groups discussion that validity.badInput is set to true, and it is -- The problem is that this is hard to test for. It doesn't seem to happen when the value is set programmatically and the change or input event is fired.


If the value is required, then we can depend on value.length === 0 && validity.valueMissing === false --- But unfortunately, this doesn't really help for values which are not "required".

Ultimately I sort of feel like this is a browser bug. I think checking for validity.badInput is enough to accommodate browsers which provide ValidityState for HTMLInputELements, but I don't think there's any nice way to test this without selenium or something.

I've opened an issue at #304455 about it. Maybe I'm wrong, but it would be good to get people considering whether sanitizing an invalid string by simply returning an empty string is the "right thing to do". I certainly don't see any mention of doing this in the specs anywhere, unless I'm missing something.


As a note: Desktop FF (at least, FF26.0a1 (2013-09-06)) does not seem to support input[type=number] at all, which may explain why you're seeing this behaviour. Opera 12.15 behaves identically to Chrome (did they already switch to Blink for that release?). IE8 does not discard value, and it still claims that type=number, but it doesn't appear to treat it any differently from text, and there is no ValidityState that I can see.

So, I'm not sure how this is on newer versions of IE, but for other browsers it seems like we're either treated as text or we have our value discarded, which breaks the validation code.

So I think the reason why this might work well for FF is because it's actually input[type=text], heh.

But still, I don't see anything in the spec that says this should be the way it works, and I don't really feel like it's very helpful.

@caitp
Copy link
Contributor

caitp commented Oct 6, 2013

Gave it another shot, and this sort of works. demo

Definitely needs some review to improve things.

caitp pushed a commit to caitp/angular.js that referenced this issue Oct 6, 2013
Fixes angular#2144

On Chromium / Safari / Opera, currently:

When a non-numeric string is entered into an input[type=number], the browser
reports the value and innerText as the empty string.

Without the ngRequire directive, the empty string is considered a valid value.

This leads to false-positives.

The aim of this patch is to suppress these false positives on browsers which
implement the `ValidityState` object. Input directives may subscribe to check
for `ValidityState` changes, and use the ValidityState during their processing.

This allows the differentiation between "valid" and "invalid" empty strings.
@caitp
Copy link
Contributor

caitp commented Oct 13, 2013

oh god, sorry about the spam :(

caitp pushed a commit to caitp/angular.js that referenced this issue Oct 20, 2013
On Chromium / Safari / Opera, currently:

When a non-numeric string is entered into an input[type=number], the browser
reports the value and innerText as the empty string.

Without the ngRequire directive, the empty string is considered a valid value.

This leads to false-positives.

The aim of this patch is to suppress these false positives on browsers which
implement the `ValidityState` object. Input directives may subscribe to check
for `ValidityState` changes, and use the ValidityState during their processing.

This allows the differentiation between "valid" and "invalid" empty strings.

Closes angular#2144
@IgorMinar
Copy link
Contributor

repro for 1.2.7 with better instructions: http://plnkr.co/edit/kuUokX?p=preview

(I noticed too late that there is a PR with a fix already, so I'm posting it anyway since I updated the plunk already)

@ghost ghost assigned caitp Jan 9, 2014
@caitp
Copy link
Contributor

caitp commented Jan 9, 2014

yeah... my PR needs a lot of review, and probably needs a pretty hefty rebase since cdc4d48 was merged. I'm not really convinced it will be ready for this week, but it might not hurt to move it to 1.2.9 so I have time to clean it up a bit, and figure out how to get a more meaningful test passing.

caitp added a commit to caitp/angular.js that referenced this issue Jan 23, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
caitp added a commit to caitp/angular.js that referenced this issue Jan 23, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
caitp added a commit to caitp/angular.js that referenced this issue Jan 23, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
caitp added a commit to caitp/angular.js that referenced this issue Jan 23, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
@tbosch tbosch modified the milestones: 1.2.12, 1.2.11, 1.2.13 Feb 3, 2014
@btford btford modified the milestones: 1.2.14, 1.2.13 Feb 15, 2014
caitp added a commit to caitp/angular.js that referenced this issue Feb 21, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
caitp added a commit to caitp/angular.js that referenced this issue Feb 21, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
caitp added a commit to caitp/angular.js that referenced this issue Feb 21, 2014
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes angular#4293
Closes angular#2144
Closes angular#4857
Closes angular#5120
Closes angular#4945
Closes angular#5500
@caitp caitp closed this as completed in c2d447e Feb 21, 2014
paoloantinori added a commit to paoloantinori/hawtio that referenced this issue May 27, 2014
paoloantinori added a commit to paoloantinori/hawtio that referenced this issue May 27, 2014
@axelson
Copy link

axelson commented May 20, 2015

Is it correct to say that when an invalid number is entered in Chrome on an input of type number that it will always be marked invalid and Angular can only get a blank string? Thus there is no way to support entering commas on a numeric input.

@gkalpak
Copy link
Member

gkalpak commented May 20, 2015

Pretty much :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.