76

私はパスワード検証ディレクティブを書いています:

 Directives.directive("passwordVerify",function(){
    return {
        require:"ngModel",
        link: function(scope,element,attrs,ctrl){
            ctrl.$parsers.unshift(function(viewValue){
                var origin = scope.$eval(attrs["passwordVerify"]);
                if(origin!==viewValue){
                    ctrl.$setValidity("passwordVerify",false);
                    return undefined;
                }else{
                    ctrl.$setValidity("passwordVerify",true);
                    return viewValue;
                }
            });

        }
    };
});

html :

<input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
<input data-ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">

フォームに 2 つのパスワード フィールドがある場合、両方のパスワード値が等しい場合、ディレクティブの影響を受けるフィールドは有効です。問題は、それが一方向にしか機能しないことです (つまり、パスワード確認フィールドにパスワードを入力したとき)。ただし、元のパスワード フィールドが更新されると、password-verify は有効になりません。

「双方向バインディング検証」を行う方法はありますか?

4

24 に答える 24

114

値 1 または値 2 が変更されたかどうかに関係なく、両方の入力フィールドを再検証したいので、次のディレクティブを使用します。

指令:

'use strict';

angular.module('myApp').directive('equals', 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('equals', function (val) {
        validate();
      });

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

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

利用方法

<input type="password" ng-model="value1" equals="{{value2}}" required>
<input type="password" ng-model="value2" equals="{{value1}}" required>
于 2013-08-02T10:42:57.970 に答える
60

これで解決するはずです:

意見:

<div ng-controller='Ctrl'>
   <form name='form'>
      <input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
      <div ng-show="form.password.$error.required">
        Field required</div>
      <input ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">
      <div ng-show="form.confirm_password.$error.required">
        Field required!</div>
      <div ng-show="form.confirm_password.$error.passwordVerify">
        Fields are not equal!</div>
   </form
</div>

指令

var app = angular.module('myApp', []);

app.directive("passwordVerify", function() {
   return {
      require: "ngModel",
      scope: {
        passwordVerify: '='
      },
      link: function(scope, element, attrs, ctrl) {
        scope.$watch(function() {
            var combined;

            if (scope.passwordVerify || ctrl.$viewValue) {
               combined = scope.passwordVerify + '_' + ctrl.$viewValue; 
            }                    
            return combined;
        }, function(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;
                    }
                });
            }
        });
     }
   };
});
于 2012-12-23T16:15:11.573 に答える
8

https://github.com/wongatech/angular-confirm-fieldは、これに適したプロジェクトです。

ここの例http://wongatech.github.io/angular-confirm-field/

以下のコードは、実装された機能を持つ 2 つの入力フィールドを示しています。

<input ng-confirm-field ng-model="emailconfirm" confirm-against="email" name="my-email-confirm"/>
<input ng-model="email" name="my-email" />
于 2014-08-07T09:18:02.480 に答える
8

angular 1.3.0-beta12 の時点で、無効な入力は ngModel に書き込まれないため、ここで確認できるように、監視してから検証することはできません: http://plnkr.co/edit/W6AFHF308nyKVMQ9vomw?p=preview。新しいバリデータ パイプラインが導入され、これにアタッチして同じことを実現できます。

実際、その点について、一般的な追加バリデーター用のバワー コンポーネントを作成しました: https://github.com/intellix/angular-validatorsで、これが含まれています。

angular.module('validators').directive('equals', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attrs, ngModel)
        {
            if (!ngModel) return;

            attrs.$observe('equals', function() {
                ngModel.$validate();
            });

            ngModel.$validators.equals = function(value) {
                return value === attrs.equals;
            };
        }
    };
});

angular.module('validators').directive('notEquals', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attrs, ngModel)
        {
            if (!ngModel) return;

            attrs.$observe('notEquals', function() {
                ngModel.$validate();
            });

            ngModel.$validators.notEquals = function(value) {
                return value === attrs.notEquals;
            };
        }
    };
});
于 2014-07-30T08:19:06.153 に答える
7

私は同じ問題を扱っていて、Piotr Buda によって書かれたそれについての良いブログ投稿を見つけました。読みやすく、プロセスを非常によく説明しています。コードは次のとおりです。

directives.directive("repeatPassword", function() {
    return {
        require: "ngModel",
        link: function(scope, elem, attrs, ctrl) {
            var otherInput = elem.inheritedData("$formController")[attrs.repeatPassword];

            ctrl.$parsers.push(function(value) {
                if(value === otherInput.$viewValue) {
                    ctrl.$setValidity("repeat", true);
                    return value;
                }
                ctrl.$setValidity("repeat", false);
            });

            otherInput.$parsers.push(function(value) {
                ctrl.$setValidity("repeat", value === ctrl.$viewValue);
                return value;
            });
        }
    };
});

したがって、次のようなことができます。

<input type="password" name="repeatPassword" id="repeatPassword" placeholder="repeat password" ng-model="user.repeatPassword" repeat-password="password" required>

クレジットは著者に帰属します

于 2013-09-25T05:36:24.103 に答える
7

以前にこのディレクティブを使用して成功しました:

 .directive('sameAs', function() {
  return {
    require: 'ngModel',
    link: function(scope, elm, attrs, ctrl) {
      ctrl.$parsers.unshift(function(viewValue) {
        if (viewValue === scope[attrs.sameAs]) {
          ctrl.$setValidity('sameAs', true);
          return viewValue;
        } else {
          ctrl.$setValidity('sameAs', false);
          return undefined;
        }
      });
    }
  };
});

使用法

     <input ... name="password" />
    <input type="password" placeholder="Confirm Password" 
name="password2" ng-model="password2" ng-minlength="9" same-as='password' required>
于 2013-08-01T18:50:01.070 に答える
3

このソリューションは、$validators を使用する Dominic Watson によって提供されたものに似ており、私が最も気に入っています。唯一の変更点は、式を見ることができることです。

$validators モデル値が変更されるたびに適用されるバリデーターのコレクション。オブジェクト内のキー値はバリデーターの名前を参照し、関数は検証操作を参照します。検証操作にはモデル値が引数として提供され、その検証の応答に応じて true または false の値を返す必要があります。

https://code.angularjs.org/1.3.15/docs/api/ng/type/ngModel.NgModelControllerから

私はAngular 1.3を使用しています。私のディレクティブは次のようになります

angular.module('app').directive("passwordConfirm", function() {
    "use strict";
    return {
        require : "ngModel",
        restrict : "A",
        scope : {
            //We will be checking that our input is equals to this expression
            passwordConfirm : '&'
        },
        link : function(scope, element, attrs, ctrl) {
            //The actual validation
            function passwordConfirmValidator(modelValue, viewValue) {
                return modelValue == scope.passwordConfirm();
            }
            //Register the validaton when this input changes
            ctrl.$validators.passwordConfirm = passwordConfirmValidator;
            //Also validate when the expression changes
            scope.$watch(scope.passwordConfirm, ctrl.$validate);
        }
    };
});

使用するには

<input type="password" ng-model="user.password"/>
<input type="password" ng-model="user.confirmPassword" 
                password-confirm="user.password" />
于 2015-11-22T00:24:13.857 に答える
2

これは両方の方法で機能し、シンプルでクリーンです

JavaScript

var app = angular.module("app");

app.controller("SamePaswordController", function () {

  this.password;
  this.confirm;

  this.save = function () {
    alert("Saved!");
  };
}


app.directive("match", function () {
  return {
    restrict:"A",
    require:"ngModel",

    link: function(scope, element, attrs, ctrl) {

      function matchValidator(value) {      

        scope.$watch(attrs.match, function(newValue, oldValue) {

          var isValid = value === scope.$eval(attrs.match);                    
          ctrl.$setValidity('match', isValid);

        });

        return value;
      }

      ctrl.$parsers.push(matchValidator);
    }
  };
});

HTML: match ディレクティブに注意してください

<form name="regForm" ng-controller="SamePaswordController as regCtrl"
      ng-submit="regForm.$valid && regCtrl.save()" novalidate>

  <input name="password" ng-model="regCtrl.password" 
         type="password" required placeholder="Password"/>                

  <input name="confirm" ng-model="regCtrl.confirm" match="regCtrl.password"
         type="password" required placeholder="Confirm password"/>


  <div> regForm is valid:{{regForm.$valid}}</div>

  <input type="submit" value="Save"/>

</form>

この例でリポジトリを複製でき ます https://github.com/rogithub/roangularjs

于 2015-04-03T20:44:43.413 に答える
0

これは私にとってはうまくいきました。

指令:

modulename.directive('passwordCheck', 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

            var Value = null;

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


                validate();
            });

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

            var validate = function () {

                // values
                var val1 = Value;
                var val2 = attrs.passwordCheck;

                // set validity

                if (val1 != '' && val1 != undefined) {
                    ngModel.$setValidity('passwordCheck', val1 == val2);

                }

                else {
                    ngModel.$setValidity('passwordCheck', true);
                }
            };
        }
    }
});

HTML:

ng-model="confirmpassword.selected" type="password" name="confirmpassword" 

password-check="{{password.selected}}"

ng-show="resetpasswordform.confirmpassword.$error.passwordCheck && submitted" Password does not match
于 2015-05-07T10:16:32.553 に答える
0

まず、この素晴らしい例を投稿してくれた Fredric に感謝します。偶然見つけた小さな問題が 1 つあります。あなたが投稿したフィドルでhttp://jsfiddle.net/gUSZS/

パスワードを入力し、次に検証入力要素に同じパスワードを入力すると、すべて正常に機能しますが、2 番目のボックスにスペースを追加しようとすると、angular がそのスペースを自動的にトリミングします。これは、ディレクティブが余分なスペースを「認識」しないことを意味します。パスワードは異なりますが、フォームは引き続き有効です。

これを修正するには、追加する必要があります

ng-trim="false"

入力要素に。これは angular 1.0.3 では機能しないため、このフィドルで試してみたい場合は、フィドルに 1.1.1 を追加する必要があります ( http://ajax.googleapis.com/ajax/libs/angularjs/1.1.1/angular .js )

しかし、フレデリックに感謝します。アプリであなたのソリューションを使用します!

Anton PS Frederic の投稿にコメントしたかったのですが、このフォーラムは初めてで、十分なクレジットがないようです。したがって、気に入った場合は、私のコメントに賛成票を投じていただければ幸いです:-)

于 2014-07-14T13:37:36.747 に答える
0
   <input name="password" type="text" required="" ng-model="password" placeholder="password" class="ng-dirty ng-valid ng-valid-required">
   <input name="confirm_password" type="text" required="" ng-model="confirm_password" ui-validate=" '$value==password' " ui-validate-watch=" 'password' " placeholder="confirm password" class="ng-dirty ng-valid-required ng-invalid ng-invalid-validator"> 
   <span ng-show="form.confirm_password.$error.validator">Passwords do not match!</span>
        password errors: {
        "required": false,
        "validator": true
        }
于 2014-12-23T02:45:11.750 に答える
0

このようなものは私にとってはうまくいきます:

js:

.directive('sameAs', function() { return {
    require : 'ngModel',
    link : function(scope, elm, attrs, ngModelCtrl) {

        ngModelCtrl.$validators.sameAs = function(modelValue, viewValue) {
            var checkedVal = attrs.sameAs;
            var thisInputVal = viewValue;

            if (thisInputVal == checkedVal) {
                return true; // valid
            } else {
                return false;
            }
        };
    }
}; });

html:

<input type="password" name="password" id="password" ng-model="password" />

<input type="password" name="passwordRepeat" id="passwordRepeat" 
    ng-model="passwordRepeat" same-as="{{password}}" />
于 2016-01-18T16:59:45.923 に答える
0

追加のディレクティブは必要ありません。これについての私の見解は次のとおりです。

HTML:

<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd.$valid }">
    <input type="password" name="new_passwd" class="form-control" data-ng-model="data.new_passwd" placeholder="New Password" required data-ng-pattern="passwdRegex">
    <small class="help-block" data-ng-show="submitted && form.new_passwd.$error.required">New password is required!</small>
    <small class="help-block" data-ng-show="submitted && !form.new_passwd.$error.required && form.new_passwd.$error.pattern">New password is not strong enough!</small>
</div>

<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd_conf.$valid }">
    <input type="password" name="new_passwd_conf" class="form-control" data-ng-model="data.new_passwd_conf" placeholder="Confirm New Password" required data-ng-pattern="passwdConfRegex">
    <small class="help-block" data-ng-show="submitted && form.new_passwd_conf.$error.required">New password confirmation is required!</small>
    <small class="help-block" data-ng-show="submitted && !form.new_passwd_conf.$error.required && form.new_passwd_conf.$error.pattern">New password confirmation does not match!</small>
</div>

Javascript:

$scope.passwdRegex = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$/;
$scope.$watch('data.new_passwd', function() {
    $scope.passwdConfRegex = new RegExp(Regex.escape($scope.data.new_passwd));
});

Regex.escape() はここにあります。

魔法のように動作します!

于 2014-07-23T11:10:58.693 に答える
0

独自のディレクティブを作成しようとしたときに同じ問題が発生し、この追加で修正しました

ctrl.$validate();

ctrl は私の ngModelController です

これが私の見解です

<input type="password" match="signupCtrl.registrationData.password" name="confirmPassword" class="form-control" placeholder="Confirm Password" data-ng-model="signupCtrl.registrationData.confirmPassword" required>
        <span ng-messages="registerForm.confirmPassword.$error">
            <span ng-message="match">The Password must match</span>
        </span>

これは私の指示です

(function () {
    'use strict';
    angular.module('matchDirective', [
        // Angular modules
        // Custom modules
        // 3rd Party Modules
    ]);
})(); 
(function () {
    'use strict';
    angular
        .module('matchDirective')
        .directive('match', match);
    match.$inject = ['$window'];

    function match($window) {
        // Usage:
        //     <element match="source"></element>
        // Creates:
        //
        var directive = {
            link: link,
            restrict: 'A',
            require: 'ngModel',
        };
        return directive;

        function link(scope, element, attrs, ctrl) {
            scope.$watch(attrs['match'], function (newVal, oldVal) {
                ctrl.$validators.match = function (modelValue, viewValue) {
                    if (newVal == modelValue) {
                        return true;
                    } else {
                        return false;
                    }
                }
                ctrl.$validate();
            });
        }
    }
})();
于 2015-08-18T18:09:28.387 に答える
0

多数の既存のソリューションに追加するには、これがうまく機能します。

( Jan Laussmannの回答は、最新の AngularJS ベータ版リリースで機能しなくなりました)。

指令:

angular.module('myApp').directive('matchValidator', [function() {
        return {
            require: 'ngModel',
            link: function(scope, elm, attr, ctrl) {
                var pwdWidget = elm.inheritedData('$formController')[attr.matchValidator];

                ctrl.$parsers.push(function(value) {
                    if (value === pwdWidget.$viewValue) {
                        ctrl.$setValidity('match', true); 
                        return value;
                    }                       

                    if (value && pwdWidget.$viewValue) {
                        ctrl.$setValidity('match', false);
                    }

                });

                pwdWidget.$parsers.push(function(value) {
                    if (value && ctrl.$viewValue) {
                        ctrl.$setValidity('match', value === ctrl.$viewValue);
                    }
                    return value;
                });
            }
        };
    }])

利用方法

<input type="email" ng-model="value1" name="email" required>
<input type="email" ng-model="value2" name="emailConfirm" match-validator="email" required>

表示エラー

<div ng-if="[[yourFormName]].emailConfirm.$error">
    <div ng-if="[[yourFormName]].emailConfirm.$error.match">
        Email addresses don't match.
    </div>
</div>
于 2014-08-19T23:34:57.660 に答える