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

Commit

Permalink
fix(input): use ValidityState to determine validity
Browse files Browse the repository at this point in the history
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 #4293
Closes #2144
Closes #4857
Closes #5120
Closes #4945
Closes #5500
Closes #5944
  • Loading branch information
caitp committed Feb 21, 2014
1 parent 7551585 commit c2d447e
Showing 1 changed file with 27 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/ng/directive/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,27 @@ function validate(ctrl, validatorName, validity, value){
return validity ? value : undefined;
}


function addNativeHtml5Validators(ctrl, validatorName, element) {
var validity = element.prop('validity');
if (isObject(validity)) {
var validator = function(value) {
// Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
// perform the required validation)
if (!ctrl.$error[validatorName] && (validity.badInput || validity.customError ||
validity.typeMismatch) && !validity.valueMissing) {
ctrl.$setValidity(validatorName, false);
return;
}
return value;
};
ctrl.$parsers.push(validator);
ctrl.$formatters.push(validator);
}
}

function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var validity = element.prop('validity');
// In composition mode, users are still inputing intermediate text buffer,
// hold the listener until composition is done.
// More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
Expand Down Expand Up @@ -463,7 +483,11 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
value = trim(value);
}

if (ctrl.$viewValue !== value) {
if (ctrl.$viewValue !== value ||
// If the value is still empty/falsy, and there is no `required` error, run validators
// again. This enables HTML5 constraint validation errors to affect Angular validation
// even when the first character entered causes an error.
(validity && value === '' && !validity.valueMissing)) {
if (scope.$$phase) {
ctrl.$setViewValue(value);
} else {
Expand Down Expand Up @@ -583,6 +607,8 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
});

addNativeHtml5Validators(ctrl, 'number', element);

ctrl.$formatters.push(function(value) {
return ctrl.$isEmpty(value) ? '' : '' + value;
});
Expand Down

7 comments on commit c2d447e

@caitp
Copy link
Contributor Author

@caitp caitp commented on c2d447e Feb 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@juliemr I could use some help putting a test together for this. Theoretically, protractor E2E tests should be able to do it, however when I attempted this previously (description in #5944), I was unable to get the ValidityState to update using ptor.

When you have time, it would be really good if we could automate a test for this, or get a bit more certainty about it being impossible.

@juliemr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - to recap, root problem with testing this via webdriver is that the browsers don't seem to want to update validity after sendKeys.

I should have time to run some tests over the weekend!

@pedubreuil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi !
It seems that the problem is back with the version v1.2.15-build.2364+sha.7c34e1f : myform.numericfield.$error.number is still not updated

@caitp
Copy link
Contributor Author

@caitp caitp commented on c2d447e Mar 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedubreuil please post a reproduction, it's impossible to help you or debug without more info

@rwtnb
Copy link

@rwtnb rwtnb commented on c2d447e Mar 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chrome Version 33.0.1750.152 seems to be setting "badInput" and "valueMissing" to true at the same time.

@caitp
Copy link
Contributor Author

@caitp caitp commented on c2d447e Mar 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rseidi please post a new issue for this, with a reproduction.

@rwtnb
Copy link

@rwtnb rwtnb commented on c2d447e Mar 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@caitp Issue with reproduction posted at #6818.

Please sign in to comment.