1

I have a form with 2 password inputs.

I use a directive to validate that the 2 forms are identical to each other.

It currently works if you fill in the password1 first and the password2 second.

Problem: When you fill in password1 and password2 and they're equal, and after that you change password1, the error messages don't get updated. I would have to type in password2 again for the error messages to appear.

Template

<!-- Password1-->
        <div class="form-group"
          ng-class="{ 'has-error' : userForm.password.$touched && userForm.password.$invalid,
                      'has-success' : userForm.password.$valid }">


          <div class="col-10">
            <input class="form-control" type="password" placeholder="Password"
                name="password"
                ng-model="home.user.password"
                ng-minlength="8"
                ng-maxlength="30"
                required>

            <div class="help-block" ng-messages="userForm.password.$error" ng-if="userForm.password.$touched">
                <p ng-message="minlength">Your password is too short.</p>
                <p ng-message="maxlength">Your password is too long.</p>
                <p ng-message="required">Your password is required.</p>
            </div>
          </div>
        </div>
        <!-- Password2-->
        <div class="form-group"
          ng-class="{ 'has-error' : userForm.password2.$touched && userForm.password2.$invalid,
                      'has-success' : userForm.password2.$valid }">


          <div class="col-10">
            <input class="form-control" type="password" placeholder="Confirm your password"
                name="password2"
                ng-model="home.user.password2"
                ng-minlength="8"
                ng-maxlength="30"
                password-verify="home.user.password"
                required>

            <div class="help-block" ng-messages="userForm.password2.$error" ng-if="userForm.password2.$touched">
                <p ng-message="passwordVerify">Passwords do not match.</p>
            </div>
          </div>
        </div>

passwordVerify directive

.directive('passwordVerify', passwordVerify);


  function passwordVerify() {
    var directive = {}

    directive.require = "ngModel";
    directive.scope = { passwordVerify: '=' };
    directive.link = verifyPassword;

    return directive;

    function verifyPassword(scope, element, attrs, ctrl) {
      scope.$watch('passwordVerify', WatcherPassword1, callback);
      scope.$watch(WatcherPassword2, callback);

      function WatcherPassword1() {
        var combined;
        console.log(scope.passwordVerify);
        if (scope.passwordVerify || ctrl.$viewValue) {
           combined = scope.passwordVerify + '_' + ctrl.$viewValue;
        }
        return combined;
      }

      function WatcherPassword2() {
        var combined;
        console.log(ctrl.$viewValue);
        if (scope.passwordVerify || ctrl.$viewValue) {
           combined = scope.passwordVerify + '_' + ctrl.$viewValue;
        }
        return combined;
      }

      function callback(value) {
        if (value) {
            ctrl.$parsers.unshift(function(viewValue) {
                var origin = scope.passwordVerify;
                if (origin !== viewValue) {
                    ctrl.$setValidity("passwordVerify", false);
                    return undefined;
                } else {
                    ctrl.$setValidity("passwordVerify", true);
                    return viewValue;
                }
            });
        }
      }

    }

  }

1 Answer 1

1

I think you need also $watch first input password model in directive

UPDATE

So I found the problem, $watchers areworking good, it was not working because of ctrl.$parsers.unshift. ctrl.$parsers.unshift executes only if ctrl was modified by user. Check my JSFiddle example

   .directive('passwordVerify', passwordVerify);

    function passwordVerify() {
       return {
          require: "ngModel",
          scope: {
            passwordVerify: '='
          },
          link: function(scope, element, attrs, ctrl) {

            function checkPasswords(){

                console.log(viewValue);
                var origin = scope.passwordVerify;
                if (origin !== ctrl.$viewValue) {
                    ctrl.$setValidity("passwordVerify", false);
                    return undefined;
                } else {
                    ctrl.$setValidity("passwordVerify", true);
                    return ctrl.$viewValue;
                }
               });


            scope.$watch('passwordVerify', function(){

                 // first input changed


            }, function(){
                 checkPasswords()
             })             

            scope.$watch(function() {       

                ... code here ...
            }, function(){
                   checkPasswords()
            })
Sign up to request clarification or add additional context in comments.

1 Comment

I've tried to add 2 watchers now. But I can't get it to work still. Could you take a look at my new directive code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.