angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.82k stars 27.5k forks source link

input validation error with type number and IE #10981

Open SlippySken opened 9 years ago

SlippySken commented 9 years ago

Hello there,

I have a problem with an input field, which only should accept numbers. In FF and Chrome everything is fine, but with IE something is wrong. If I enter '123asd' an error message appears. But if I enter 'asd123' no error message appears. Here a plnkr :).

http://plnkr.co/edit/9qsIf2mGnkbFIJ8bb0MW?p=preview

matsko commented 9 years ago

Which version(s) of IE is this problem showing up on?

matsko commented 9 years ago

Older versions of IE don't have support for things like type="number": http://caniuse.com/#feat=form-validation

This should however be emulated properly in Angular if this is the case.

SlippySken commented 9 years ago

I'm using IE 11 :(

matsko commented 9 years ago

This is definitely an issue. @petebacondarwin @caitp @Narretz @shahata can one of you look into this please?

petebacondarwin commented 9 years ago

The problem is down to the way that IE parses the value of number input boxes. I think that it is naively using parseFloat or maybe parseInt. These methods have the following annoying behaviour:

parseFloat('30', 10)
30
parseFloat('30a', 10)
30
parseFloat('a30', 10)
NaN

I reckon that IE just parses the number and assigns the empty string to the value if it gets NaN.

So if the value of the text input goes from an empty string to a string that starts with a non-number then IE doesn't trigger a change event, since as far as it is concerned the value has not changed (it was empty before and is empty now).

Ironically, because of the way it is parsing for a number, if the value of the input starts with a number followed by letters, then IE does think that it is a number.

petebacondarwin commented 9 years ago

Actually, let me qualify this a bit further. The "value sanitization" rules I described above are actually part of the spec and it is what is implemented by most modern browsers, including IE and Chrome.

It seems that the real problem is that IE is not triggering an ngModel update in the case described above. In Chrome we get a "input" event occurring even though the element value is still empty.

petebacondarwin commented 9 years ago

It gets more complicated!

So for one reason or another, we don't listen to the "input" event in IE<=11. What we do listen to instead is the "keydown" event. This does get triggered but unlike the handler for "input", which just calls the listener function directly, the handler for "keydown" calls deferListener which has an additional check of whether the input element has changed or not. If not then we don't actually call listener at all.

Hmm. So either we need to work out whether we can listen to input for IE11, or we remove the check of whether the value has changed, or we find some other way (perhaps by running validation, whether or not the input element value has changed...)

petebacondarwin commented 9 years ago

I think we need the deferListener to cope with async updates to the value that are triggered by a keydown.

Narretz commented 9 years ago

This sounds like the same issue as this: https://github.com/angular/angular.js/issues/7070, although @caitp came to a different conclusion as it seems.

The problem is not a missing input event, but that IE does not set badInput correctly.

IE 11: 0a: input value is 0a, badInput is undefined a0: input valie is '', badInput is undefined

Firefox: 0a: input value is '', badInput is true a0: input value is '', badInput is true

So in the case of 0a our secondary mechanism of checking number validity works, but with a0, we have no way of checking the validity because no value is reported and badInput isn't set.

petebacondarwin commented 9 years ago

@Narretz - thanks for that link. Yes I think @caitp is right here that badInput is not set correctly in IE.

Here is a plunker to see what events are happening: http://plnkr.co/edit/el58Dle0EGR2U2mbGWuN?p=preview

But even if this were fixed, we would not get to the badInputChecker $parser in IE since, in deferListener we are checking the value of the element against its previous value before running the listener.

You can see this is the case if you consider these two ways of getting to "asd123":

petebacondarwin commented 9 years ago

I agree with putting in the IceBox until the IE11 bug is fixed. Does this happen with IE12?

Narretz commented 9 years ago

I think you need Windows 10 to test IE12, so I cannot say. The issue is still open on connect.microsoft: https://connect.microsoft.com/IE/feedback/details/850187/html5-constraint-validation-is-broken-in-ie11-for-input-type-number

Should we close the other issue? This here has more info.

Narretz commented 9 years ago

I got my hand ony Windows 10 + IE 11 and this is still broken in the normal IE (Trident) engine, but it works with the new EdgeHTML engine which is default in the new Spartan browser. I'm not sure if IE12 will have EdgeHtml as standard engine when released.

zendu commented 6 years ago

Is there any workaround? Will adding ngPattern validation work?

bbortt commented 6 years ago

Although this issue is already closed..

@zendu ngPattern validation would work but has not the very same behaviour. You could still input alphabetic characters but the validation would fail. I personally used a (change) listener and dropped the event if the given input didn't match ^\d{0,}$ which equals any integer. Adapt the regex to match any floating values. Might not be the very best solution but works :)

chce commented 6 years ago

This issue is still open, bbortt