Validating Password And Confirm Password Fields Wh

2020-03-03 05:10发布

I currently have an Angular Directive that validates a password and confirm password field as matching. It works to a point, it does throw an error when the passwords do not match. However, it doesn't throw the error until you have entered data in both fields. How can I make it so the error for mismatched passwords is thrown as soon as you enter data in one field or the other?

Here is the directive (it has to be added to both fields that need to match):

.directive('passwordVerify', function() {
   return {
      restrict: 'A', // only activate on element attribute
      require: '?ngModel', // get a hold of NgModelController
      link: function(scope, elem, attrs, ngModel) {
         //if (!ngModel) return; // do nothing if no ng-model

         // watch own value and re-validate on change
         scope.$watch(attrs.ngModel, function() {
            validate();
         });

         // observe the other value and re-validate on change
         attrs.$observe('passwordVerify', function(val) {
            validate();
         });

         var validate = function() {
            // values
            var val1 = ngModel.$viewValue;
            var val2 = attrs.passwordVerify;

           // set validity
           ngModel.$setValidity('passwordVerify', !val1 || !val2 || val1 === val2);
        };
      }
   };
});

And here is the directive in my form:

<div class="small-5 columns">
    <div class="small-12 columns">
        <label>
            Password
            <input 
                ng-class="{ notvalid: submitted && add_user_form.user_password.$invalid }" 
                class="instructor-input" 
                id="user_password" 
                type="password" 
                name='user_password' 
                placeholder="password" 
                value='' 
                required 
                ng-model="user.user_password" 
                password-verify="[[user.confirm_password]]"
            >
        </label>
        <p class="help-text">
            <span class="   ">Required</span>
        </p>
        <div 
            class="help-block" 
            ng-messages="add_user_form.user_password.$error" 
            ng-show="add_user_form.user_password.$touched || add_user_form.user_password.$dirty"
        >
        <span class="red">
            <div ng-messages-include="/app/views/messages.html" ></div>
        </span>
    </div>
</div>
<div class="small-12 columns">
    <label>
        Confirm Password
        <input 
            ng-class="{ notvalid: submitted && add_user_form.confirm_password.$invalid }" 
            class="instructor-input" 
            id="confirm_password" 
            ng-model="user.confirm_password" 
            name="confirm_password" 
            type="password" 
            placeholder="confirm password" 
            name="user_confirm_passsword" 
            required 
            password-verify="[[user.user_password]]"
        >
    </label>
    <p class="help-text">
        <span class="   ">
            Enter matching password
        </span>
    </p>
    <div 
        class="help-block" 
        ng-messages="add_user_form.confirm_password.$error" 
        ng-show="add_user_form.confirm_password.$dirty || add_user_form.confirm_password.$touched "
    >
        <span class="red">
            <div 
                ng-messages-include="/app/views/messages.html"
            ></div>
        </span>
    </div>
</div>

6条回答
我想做一个坏孩纸
2楼-- · 2020-03-03 05:21

This is what worked for me (ugly and hackish):

HTML:

<h1>Password Verification</h1>
<form name="pw" ng-controller="pw">
<p>
  <label for="password">New Password
    <input type="password" name="user_password" ng-model="user_password" ng-required="confirm_password && !user-password" password-verify="confirm_pasword">
    <p ng-show="pw.user_password.$error.passwordVerify">Passwords do not match</p>
    <p ng-show="pw.user_password.$error.required">This field is required</p>
  </label>
</p>
 <p>
  <label for="password">Confirm Password
    <input type="password" name="confirm_password" ng-model="confirm_password" ng-required="user_password && !confirm_password" password-verify="user_password"> 
    <p ng-show="pw.confirm_password.$error.passwordVerify">Passwords do not match</p>
    <p ng-show="pw.confirm_password.$error.required">This field is required</p>
  </label>
</p>
</form>

Then the script:

angular.module('app', [])
.controller('pw', ['$scope', function($scope){
    $scope.user_password = "";
    $scope.confirm_password = "";

}])
.directive('passwordVerify', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attrs, ngModel) {
            scope.$watch(attrs.ngModel, function() {
                if (scope.confirm_password === scope.user_password) {
                    scope.pw.confirm_password.$setValidity('passwordVerify', true);
                    scope.pw.user_password.$setValidity('passwordVerify', true);
                } else if (scope.confirm_password !== scope.user_password) {
                    scope.pw.confirm_password.$setValidity('passwordVerify', false);
                    scope.pw.user_password.$setValidity('passwordVerify', false);
                }
            });
        }
     };
});
查看更多
Root(大扎)
3楼-- · 2020-03-03 05:25

Here is a simple working solution. We can simply use $validators introduced in Angular 1.3.0 to achieve the same:

var app = angular.module("sa", []);

app.controller("FooController", function($scope) {

});

app.directive('passwordVerify', function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elem, attrs, ngModel) {
      ngModel.$validators.myPwdInvalid = function(modelValue, viewValue) {
        return viewValue === scope.$eval(attrs.passwordVerify);
      };
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>

<form name="add_user_form" ng-app="sa" ng-controller="FooController">
    <div class="small-12 columns">
        <label>Password
            <input ng-class="{ notvalid: add_user_form.user_password.$invalid }"
                   type="password" name='user_password' placeholder="password" required
                   ng-model="user.user_password" password-verify="user.confirm_password">
        </label>

        <div class="help-block" ng-messages="add_user_form.user_password.$error"
             ng-show="add_user_form.user_password.$error.$dirty || add_user_form.user_password.$touched">
            <div ng-messages="myPwdInvalid">Password do not match</div>
        </div>
    </div>

    <div class="small-12 columns">
        <label>Confirm Password
            <input ng-class="{ notvalid: add_user_form.confirm_password.$invalid }"
                   ng-model="user.confirm_password"
                   name="confirm_password" type="password" placeholder="confirm password" required
                   password-verify="user.user_password">
        </label>

        <div class="help-block" ng-messages="add_user_form.confirm_password.$error"
             ng-show="add_user_form.confirm_password.$error.$dirty || add_user_form.confirm_password.$touched">
            <div ng-messages="myPwdInvalid">Password do not match</div>
        </div>
    </div>
</form>

查看更多
beautiful°
4楼-- · 2020-03-03 05:28

Here is an easy to understand solution:

<input class="form-control" type="password" name="newpass"  ng-model="newpass">
<input class="form-control" type="password" name="confirmpass"  ng-model="confirmpass">
<div  ng-show="confirmpass != newpass"><hr>Password not matched</div>
查看更多
Root(大扎)
5楼-- · 2020-03-03 05:30

Just change the last check:

ngModel.$setValidity('passwordVerify', !val1 || !val2 || val1 === val2);

to:

ngModel.$setValidity('passwordVerify', val1 === val2);

Here's a working version:

(function() {
  "use strict";
  angular
    .module('app', ['ngMessages'])
    .controller('mainCtrl', mainCtrl)
    .directive('passwordVerify', passwordVerify);

  function mainCtrl($scope) {
    // Some code
  }

  function passwordVerify() {
    return {
      restrict: 'A', // only activate on element attribute
      require: '?ngModel', // get a hold of NgModelController
      link: function(scope, elem, attrs, ngModel) {
        if (!ngModel) return; // do nothing if no ng-model

        // watch own value and re-validate on change
        scope.$watch(attrs.ngModel, function() {
          validate();
        });

        // observe the other value and re-validate on change
        attrs.$observe('passwordVerify', function(val) {
          validate();
        });

        var validate = function() {
          // values
          var val1 = ngModel.$viewValue;
          var val2 = attrs.passwordVerify;

          // set validity
          ngModel.$setValidity('passwordVerify', val1 === val2);
        };
      }
    }
  }
})();
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-messages/1.5.7/angular-messages.min.js"></script>
</head>

<body ng-controller="mainCtrl">
  <form name="add_user_form">
    <div class="col-md-12">
      <div class="form-group" ng-class="{ 'has-error' : add_user_form.user_password.$dirty && add_user_form.user_password.$invalid }">
        <p class="help-text">Enter password</p>
        <input type="password" class="form-control" id="user_password" name="user_password" placeholder="password" required ng-model="user.user_password" password-verify="{{user.confirm_password}}">
        <div class="help-block" ng-messages="add_user_form.user_password.$error" ng-if="add_user_form.user_password.$dirty">
          <p ng-message="required">This field is required</p>
          <p ng-message="minlength">This field is too short</p>
          <p ng-message="maxlength">This field is too long</p>
          <p ng-message="required">This field is required</p>
          <p ng-message="passwordVerify">No match!</p>
        </div>
      </div>
      <div class="form-group" ng-class="{ 'has-error' : add_user_form.confirm_password.$dirty && add_user_form.confirm_password.$invalid }">
        <p class="help-text">Enter matching password</p>
        <input class="form-control" id="confirm_password" ng-model="user.confirm_password" name="confirm_password" type="password" placeholder="confirm password" required password-verify="{{user.user_password}}">
        <div class="help-block" ng-messages="add_user_form.confirm_password.$error" ng-if="add_user_form.confirm_password.$dirty">
          <p ng-message="required">This field is required</p>
          <p ng-message="minlength">This field is too short</p>
          <p ng-message="maxlength">This field is too long</p>
          <p ng-message="required">This field is required</p>
          <p ng-message="passwordVerify">No match!</p>
        </div>
      </div>
    </div>
  </form>
</body>

</html>

I hope it helps.

查看更多
SAY GOODBYE
6楼-- · 2020-03-03 05:30

While the above answers are correct, there is a very simple solution for this situation:

You can use a ng-class directive to set a class different from angularjs built-in class (ng-invalid) and add a simple style for it in your css. DO NOT FORGET to add !important to your style because angularjs overrides it ;)

查看更多
迷人小祖宗
7楼-- · 2020-03-03 05:35

You can simply use following.

<span class="error" ng-if="!register_frm.password.$invalid && !register_frm.confirm_password.$invalid && register_frm.password.$viewValue != register_frm.confirm_password.$viewValue">
Confirm Password must match with Password
</span>
查看更多
登录 后发表回答