1

So I'm creating directive that will match passwords. I was trying to figure out my own way to do it. And when, finally, I though I had found solution it didn't work. Here is the dricetive code:

directive('matchPass', function () {
  return {
    //restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ngModelCtrl) {
      scope.$watch(attrs.ngModel, function (n) {
        ngModelCtrl.$setValidity('matchPass', n == scope.registerForm.password.$viewValue)
      })
      scope.$watch(attrs.matchPass, function (n) {
        ngModelCtrl.$setValidity('matchPass', n == scope.registerForm.password.$viewValue)
      })
    }
  }
})

The problem is here

scope.$watch(attrs.matchPass...

It doesn't fire, the first one works fine. I'm stuck and lost.

View code

<div class="marginAuto">
        <md-input-container>
            <label>Password</label>
            <input required="" name="password" ng-model="password" type="password" ng-minlength="8" ng-maxlength="30">
            <div ng-messages="registerForm.password.$error">
              <div ng-message="required">This is required!</div>
              <div ng-message-exp="['required', 'minlength', 'maxlength']">
                  8 - 30 characters!
              </div>
            </div>
        </md-input-container>
    </div>
    <div class="marginAuto">
        <md-input-container>
            <label>Repeat password</label>
            <input required name="repassword" ng-model="repassword" type="password" match-pass="password">
            <div ng-messages="registerForm.repassword.$error" na>
              <div ng-message="required">This is required!</div>
            </div>
        </md-input-container>
    </div>
    <div class='msg-block' ng-show='registerForm.$error'>
      <span class='msg-error' ng-show='registerForm.repassword.$error.matchPass'>
        Passwords don't match.
      </span>
    </div>
Mohammad Sadiqur Rahman
  • 5,379
  • 7
  • 31
  • 45
lkwsk
  • 33
  • 5
  • it isn't working because `ng-model` value stays undefined until `ng-minlength` doesn't get exceeded.. checkout [**Why does setting ng-model to undefined**](http://stackoverflow.com/a/28338146/2435473) for more details – Pankaj Parkar Dec 07 '16 at 21:56

2 Answers2

0

You could try getting rid of $watch and use ng-change instead, something like the below should work out for you.

So change up the directive to have a function instead of a watch.

directive('matchPass', function () {
  return {
    //restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ngModelCtrl) {

      ngModelCtrl.$setValidity('matchPass', false);

      scope.checkMatch = function(password, repassword) {
        if (password === repassword) {
            ngModelCtrl.$setValidity('matchPass', true);
        } else {
            ngModelCtrl.$setValidity('matchPass', false);
        }
      })
    }
  }
})

Now the only tweak below is replaceing the directive attribute

<div class="marginAuto">
        <md-input-container>
            <label>Password</label>
            <input required="" name="password" ng-model="password" type="password" ng-minlength="8" ng-maxlength="30">
            <div ng-messages="registerForm.password.$error">
              <div ng-message="required">This is required!</div>
              <div ng-message-exp="['required', 'minlength', 'maxlength']">
                  8 - 30 characters!
              </div>
            </div>
        </md-input-container>
    </div>
    <div class="marginAuto">
        <md-input-container>
            <label>Repeat password</label>
            <input required name="repassword" ng-model="repassword" type="password" ng-change="checkMatch(password, repassword)">
            <div ng-messages="registerForm.repassword.$error" na>
              <div ng-message="required">This is required!</div>
            </div>
        </md-input-container>
    </div>
    <div class='msg-block' ng-show='registerForm.$error'>
      <span class='msg-error' ng-show='registerForm.repassword.$error.matchPass'>
        Passwords don't match.
      </span>
    </div>
0

I came up with my own solution.

link: function (scope, element, attrs, ngModelCtrl) {  
      if (!scope.registerForm[attrs.matchPass].$invalid) {
        scope.$watchGroup([attrs.ngModel, attrs.matchPass], function (n) {
          console.log(n)
          ngModelCtrl.$setValidity('matchPass', n[0] === n[1])
        })
      }

It works well.

lkwsk
  • 33
  • 5