angularjs 中的密码检查指令

IT技术 javascript angularjs
2021-01-21 12:51:10

我正在编写密码验证指令:

 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 个密码字段,如果两个密码值相等,则受指令影响的字段有效。问题是它以一种方式工作(即当我在密码验证字段中输入密码时)。但是,当原始密码字段被更新时,密码验证不会生效。

知道如何进行“双向绑定验证”吗?

6个回答

我使用以下指令是因为我想重新验证两个输入字段,无论值 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>
ngModel.$setValidityif (val1 && val2) { .. }只是这样当两个值都为空时表单不是无效的。
2021-03-20 12:51:10
我认为最好替换ngModel.$setValidity('equals', val1 === val2);ngModel.$setValidity('equals', ! val1 || ! val2 || val1 === val2);
2021-03-26 12:51:10
我发现这工作得很好。让我措手不及的一件事是,如果您有其他一些角度验证器,例如:ng-minlength在第一个字段上,那么该模型在实际有效之前不会设置
2021-04-04 12:51:10
这对我很有用。作为新手,将验证字符串添加到此会有所帮助。[form name].[field name].$error.equals使用它来控制应该或应该显示哪些字段。我将它用于错误标签。
2021-04-06 12:51:10
当有更多验证规则在起作用时,这会产生一些小问题。如果另一个验证失败,Angular 不会更新模型,并且在比较中会发生奇怪的事情......
2021-04-11 12:51:10

不需要为此创建单独的指令。已经有一个内置的 Angular UI 密码验证工具有了这个,你可以这样做:

<input name="password" required ng-model="password">
<input name="confirm_password"
       ui-validate=" '$value==password' "
       ui-validate-watch=" 'password' ">

 Passwords match? {{!!form.confirm_password.$error.validator}}
我和原来的帖子有同样的问题。如果 angular-ui 已经内置了一些东西,使用它而不是重新发明轮子是否有意义?
2021-03-17 12:51:10
@DominicWatson 指令在这里github.com/angular-ui/ui-utils/blob/master/modules/validate/...除了在 jquery lite 中没有异常的 jquery。如果你如此反 jquery,你不应该使用这个框架,因为它包含了 jquery。
2021-04-02 12:51:10
目前需要 jQuery
2021-04-07 12:51:10
@DominicWatson 你为什么不给我投票?这个问题是关于 angular 的,我参考了 angular 文档。如果您不了解它们之间的区别,请去学习它。
2021-04-07 12:51:10
@PeterG 我不认为多米尼克·沃森知道他在说什么
2021-04-11 12:51:10

这应该解决它:

看法:

<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;
                    }
                });
            }
        });
     }
   };
});
该方案有一个重大缺陷:如果用户正确输入了2个密码,然后更改了第一个密码(即user.password模型),则不会触发错误。
2021-03-19 12:51:10
我同意 CWSpear。该解决方案应使用上面评论的错误进行更正
2021-03-29 12:51:10
我使用了文档中的验证片段,让我试试你的代码。
2021-03-31 12:51:10
我已经改变了我的答案。这应该有效。jsFiddle
2021-03-31 12:51:10
此解决方案存在内存泄漏。通过将另一个解析器推送到 ctrl.$parsers 数组而触发的每个监视事件。在 watch 事件处理程序末尾检查 ctrl.$parsers.length 将显示这一点。
2021-04-01 12:51:10

对此的另一种看法是将一个输入的模型与另一个输入的值相匹配。

app.directive('nxEqual', function() {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, model) {
            if (!attrs.nxEqual) {
                console.error('nxEqual expects a model as an argument!');
                return;
            }
            scope.$watch(attrs.nxEqual, function (value) {
                model.$setValidity('nxEqual', value === model.$viewValue);
            });
            model.$parsers.push(function (value) {
                var isValid = value === scope.$eval(attrs.nxEqual);
                model.$setValidity('nxEqual', isValid);
                return isValid ? value : undefined;
            });
        }
    };
});

因此,如果密码框的模型是,login.password那么您在验证框上设置以下属性:nx-equal="login.password",并测试formName.elemName.$error.nxEqual. 像这样:

<form name="form">
    <input type="password" ng-model="login.password">
    <input type="password" ng-model="login.verify" nx-equal="login.password" name="verify">
    <span ng-show="form.verify.$error.nxEqual">Must be equal!</span>
</form>

扩大的视野:

对于我的一个新项目,我不得不修改上述指令,以便它仅nxEqual在验证输入具有值时才显示错误。否则nxEqual应该消除错误。这是扩展版本:

app.directive('nxEqualEx', function() {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, model) {
            if (!attrs.nxEqualEx) {
                console.error('nxEqualEx expects a model as an argument!');
                return;
            }
            scope.$watch(attrs.nxEqualEx, function (value) {
                // Only compare values if the second ctrl has a value.
                if (model.$viewValue !== undefined && model.$viewValue !== '') {
                    model.$setValidity('nxEqualEx', value === model.$viewValue);
                }
            });
            model.$parsers.push(function (value) {
                // Mute the nxEqual error if the second ctrl is empty.
                if (value === undefined || value === '') {
                    model.$setValidity('nxEqualEx', true);
                    return value;
                }
                var isValid = value === scope.$eval(attrs.nxEqualEx);
                model.$setValidity('nxEqualEx', isValid);
                return isValid ? value : undefined;
            });
        }
    };
});

你会像这样使用它:

<form name="form">
    <input type="password" ng-model="login.password">
    <input type="password" ng-model="login.verify" nx-equal-ex="login.password" name="verify">
    <span ng-show="form.verify.$error.nxEqualEx">Must be equal!</span>
</form>

试试看:http : //jsfiddle.net/gUSZS/

我认为它实际上默认为 true 作为子范围。不过最近没查。
2021-03-15 12:51:10
@GillBates 使用隔离范围并绑定参数 by=不会在填写后重新检查第一个输入。我制作了一个快速的JSFiddle来显示这个问题。
2021-03-25 12:51:10
这是最好的。这是最简洁的。它适用于模型值,并且可以双向工作。
2021-03-26 12:51:10
但是有一件事是 $parser 管道应该返回值或未定义。这样后续管道就不会结束,因为当没有返回函数时,它总是返回 undefined 。范围也应该是假的。
2021-03-29 12:51:10
@CMCDragonkai:抓得好!我已经更新了解析器函数的返回值。关于范围,据我所知,它默认为false,因此通过不明确指定范围,它等于scope: false
2021-04-07 12:51:10

我是在没有指令的情况下完成的。

<input type="password" ng-model="user.password" name="uPassword" required placeholder='Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
    <span class="error" ng-show="form.uPassword.$dirty && form.uPassword.$error.minlength">Too short</span>
    <span ng-show="form.uPassword.$dirty && form.uPassword.$error.required">Password required.</span><br />

    <input type="password" ng-model="user.confirmpassword" name="ucPassword" required placeholder='Confirm Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
    <span class="error" ng-show="form.ucPassword.$dirty && form.ucPassword.$error.minlength">Too short</span>
    <span ng-show="form.ucPassword.$dirty && form.ucPassword.$error.required">Retype password.</span>
    <div ng-show="(form.uPassword.$dirty && form.ucPassword.$dirty) && (user.password != user.confirmpassword)">
        <span>Password mismatched</span>
    </div>
您应该使用已经指出的指令,表单保持有效状态。否则,您也可以为它制作一些 jquery 侦听器。
2021-04-04 12:51:10