Moshe Shaham
Moshe Shaham

Reputation: 15974

Input is invalid even when it's error is empty

I'm trying to create my own validation for password confirm, and putting my error on $error. this is my code:

html:

<input ng-model="user.password2" type="password" name="password2" required 
ng-keyup="confirmPassword(user.password, user.password2)">
<div ng-messages="register.password2.$error" ng-if="register.password2.$dirty">
   <div ng-message="required">Password is required</div>
   <div ng-message="passwordsDontMatch">Passwords don't match</div>
</div>

JS:

$scope.confirmPassword = function (pass1, pass2) {
        if (angular.isUndefined(pass1) || angular.isUndefined(pass2) || pass1.trim() != pass2.trim()) {
            $scope.register.password2.$error["passwordsDontMatch"] = true;
        } else {
            delete $scope.register.password2.$error["passwordsDontMatch"];
        }
        console.log($scope.register.password2.$error);
    };

it looks like it's working. when the passwords are the same, the message is not displayed and indeed the $error object is empty. But the input is still invalid: ($scope.register.password2.$invalid == true)

you can see what I'm talking about in this plunkr: http://plnkr.co/edit/ETuVqsdSaEBWARvlt4RR?p=preview try 2 identical passwords. the message will disappear but when you blur from the input, it's still red because internally it's $invalid

Upvotes: 0

Views: 694

Answers (1)

JB Nizet
JB Nizet

Reputation: 691635

The problem probably comes from the fact that you're not typing a password in the first field that matches your regex pattern. The first password is thus undefined, since it doesn't respect the ng-pattern validation rule.

That said, you shouldn't modify the $error array directly. Instead, you should set the validity of the field using $setValidity(). That will not only set and remove the error automatically, but also deal with the $invalid/$valid properties, add and remove the CSS classes, etc.

var valid = !((angular.isUndefined(pass1) || angular.isUndefined(pass2) || pass1.trim() != pass2.trim()));
$scope.register.password2.$setValidity("passwordsDontMatch", valid);

Here's a working example. But remember to enter a valid password in the first place.

Also, instead of implementing this check with ng-keyup, you should make it a directive, which would add a validator to the validators of the form input. This would make sure the check is made whatever the way the second password is entered (i.e. via copy/paste using the mouse only, or simply by prepopulating the form programmatically.

Upvotes: 1

Related Questions