使用AngularJS比较表单验证中的两个输入值

tra*_*sis 47 forms validation angularjs

我正在尝试使用AngularJS进行表单验证.我特别感兴趣的是比较两个值.我希望用户在继续之前确认他输入的一些数据.可以说我有以下代码:

<p>
    Email:<input type="email" name="email1" ng-model="emailReg">
    Repeat Email:<input type="email" name="email2" ng-model="emailReg2">
<p>
Run Code Online (Sandbox Code Playgroud)

然后我可以使用验证:

<span ng-show="registerForm.email1.$error.required">Required!</span>
<span ng-show="registerForm.email1.$error.email">Not valid email!</span>
<span ng-show="emailReg !== emailReg2">Emails have to match!</span>  <-- see this line
Run Code Online (Sandbox Code Playgroud)

registerForm.$ valid将对输入中的文本做出正确的反应,除了我不知道如何在此验证中使用比较来强制电子邮件在允许用户提交表单之前是相同的.

我希望有一个没有自定义指令的解决方案,但如果没有它就无法实现,我会处理它.是一个解决自定义指令类似问题的答案.

任何帮助表示感谢,谢谢

Hen*_*Neo 46

您应该能够使用ng-pattern/regex来比较2个输入值

Email:<input type="email" name="email1" ng-model="emailReg">
Repeat Email:<input type="email" name="email2" ng-model="emailReg2" ng-pattern="emailReg">
Run Code Online (Sandbox Code Playgroud)

和验证:

<span ng-show="registerForm.email2.$error.pattern">Repeat Email should have the same value with email!</span>
Run Code Online (Sandbox Code Playgroud)

  • 当然,当你有正则表达式符号时,这会失败.另外我希望"test@test.com"能够匹配"test @ testacom",所以这是一个非常可怕的方法. - /test@test.com/.test('test@testacom') (3认同)
  • 这太棒了.已经实现了一个每个人似乎都建议的自定义指令,但我完全放弃它,因为这对我来说更符合"角度方式"的做法! (2认同)

Ram*_*ran 37

实现此目的的一种方法是使用自定义指令.以下是使用自定义指令的示例(ng-match在本例中):

<p>Email:<input type="email" name="email1" ng-model="emailReg">
Repeat Email:<input type="email" name="email2" ng-model="emailReg2" ng-match="emailReg"></p>

<span data-ng-show="myForm.emailReg2.$error.match">Emails have to match!</span>
Run Code Online (Sandbox Code Playgroud)

注意:通常不建议将其ng-用作自定义指令的前缀,因为它可能与官方AngularJS指令冲突.

更新

也可以在不使用自定义指令的情况下获得此功能:

HTML

<button ng-click="add()></button>
<span ng-show="IsMatch">Emails have to match!</span>
Run Code Online (Sandbox Code Playgroud)

调节器

$scope.add = function() {
  if ($scope.emailReg != $scope.emailReg2) {
    $scope.IsMatch=true;
    return false;
  }
  $scope.IsMatch=false;
}
Run Code Online (Sandbox Code Playgroud)

  • ng-match不是AngularJS框架提供的验证指令.请不要用ng-*命名自己的自定义指令.有效的现有验证器列表可在https://docs.angularjs.org/api/ng/directive/input上找到. (17认同)

Jac*_*lek 29

trainosais - 你是对的,验证应该在指令层面完成.它干净,模块化,允许代码的可重用性.当您在控制器中进行基本验证时,您已经反复为不同的表单编写了它.这是超级干燥的.

我最近遇到了类似的问题,并使用一个简单的指令对其进行了整理,该指令插入到解析器管道中,因此与Angular架构保持一致.链接验证器使其易于重用,应该被视为我视图中唯一的解决方案.

不用多说,这里是简化的标记:

<form novalidate="novalidate">
    <label>email</label>
    <input type="text"
        ng-model="email"
        name="email" />
    <label>email repeated</label>
    <input ng-model="emailRepeated"
        same-as="email"
        name="emailRepeated" />
</form>
Run Code Online (Sandbox Code Playgroud)

和JS代码:

angular.module('app', [])
    .directive('sameAs', function() {
        return {
            require: 'ngModel',
            link: function(scope, elem, attrs, ngModel) {
                ngModel.$parsers.unshift(validate);

                // Force-trigger the parsing pipeline.
                scope.$watch(attrs.sameAs, function() {
                    ngModel.$setViewValue(ngModel.$viewValue);
                });

                function validate(value) {
                    var isValid = scope.$eval(attrs.sameAs) == value;

                    ngModel.$setValidity('same-as', isValid);

                    return isValid ? value : undefined;
                }
            }
        };
    });
Run Code Online (Sandbox Code Playgroud)

该指令挂钩到解析器管道中,以便根据新视图值与参考字段值的比较获得对视图值的任何更改的通知并设置有效性.这一点很容易.棘手的一点是嗅探参考字段的变化.为此,该指令在参考值上设置了一个观察者,并且强制触发解析管道,以便再次运行所有验证器.

如果你想玩它,这是我的笔:http: //codepen.io/jciolek/pen/kaKEn

我希望它有所帮助,Jacek


Cha*_*ani 12

我最近编写了一个自定义指令,它可以通用,可以进行任何验证.它从当前范围获取验证功能

module.directive('customValidator', [function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: { validateFunction: '&' },
            link: function (scope, elm, attr, ngModelCtrl) {
                ngModelCtrl.$parsers.push(function (value) {
                    var result = scope.validateFunction({ 'value': value });
                    if (result || result === false) {
                        if (result.then) {
                            result.then(function (data) {           //For promise type result object
                                ngModelCtrl.$setValidity(attr.customValidator, data);
                            }, function (error) {
                                ngModelCtrl.$setValidity(attr.customValidator, false);
                            });
                        }
                        else {
                            ngModelCtrl.$setValidity(attr.customValidator, result);
                            return result ? value : undefined;      //For boolean result return based on boolean value
                        }
                    }
                    return value;
                });
            }
        };
    }]);
Run Code Online (Sandbox Code Playgroud)

要使用它你

<input type="email" name="email2" ng-model="emailReg2" custom-validator='emailMatch' data-validate-function='checkEmailMatch(value)'>
<span ng-show="registerForm.email2.$error.emailMatch">Emails have to match!</span>
Run Code Online (Sandbox Code Playgroud)

在您的控制器中,您可以实现该方法,该方法应返回true或false

$scope.checkEmailMatch=function(value) {
    return value===$scope.emailReg;
}
Run Code Online (Sandbox Code Playgroud)

优点是您不必为每个自定义验证编写自定义指令.


br3*_*3w5 8

当将角度升级到1.3及以上时,我发现使用Jacek Ciolek的答案很有问题:

  • 将数据添加到参考字段
  • 将相同的数据添加到带有指令的字段中(此字段现在有效)
  • 返回参考字段并更改数据(指令字段保持有效)

我测试了rdukeshier的答案(更新var modelToMatch = element.attr('sameAs')var modelToMatch = attrs.sameAs正确检索参考模型),但同样的问题发生了.

为了解决这个问题(在角度1.3和1.4中测试),我修改了rdukeshier的代码,并在参考字段上添加了一个观察器,以便在参考字段更改时运行所有验证.该指令现在看起来像这样:

angular.module('app', [])
  .directive('sameAs', function () {
    return {
      require: 'ngModel',
      link: function(scope, element, attrs, ctrl) {
        var modelToMatch = attrs.sameAs;      

        scope.$watch(attrs.sameAs, function() {
          ctrl.$validate();          
        })

        ctrl.$validators.match = function(modelValue, viewValue) {
          return viewValue === scope.$eval(modelToMatch);
        };
      }
   };
});
Run Code Online (Sandbox Code Playgroud)

更新了codepen


Exc*_*ion 5

不需要函数或指令。只需从视图中比较它们的 $modelValue :

ng-show="formName.email.$modelValue !== formName.confirmEmail.$modelValue"
Run Code Online (Sandbox Code Playgroud)

更详细的例子:

<span ng-show="(formName.email.$modelValue !== formName.confirmEmail.$modelValue) 
                && formName.confirmEmail.$touched
                && !formName.confirmEmail.$error.required">Email does not match.</span>
Run Code Online (Sandbox Code Playgroud)

请注意ConfirmEmail 在 ViewModel 之外;它是 $scope 的属性。它不需要提交。


Che*_* Li 5

使用ng-pattern,以便ng-valid和ng-dirty可以正常运行

Email:<input type="email" name="email1" ng-model="emailReg">
Repeat Email:<input type="email" name="email2" ng-model="emailReg2" ng-pattern="emailReg">

<span ng-show="registerForm.email2.$error.pattern">Emails have to match!</span>
Run Code Online (Sandbox Code Playgroud)