【问题标题】:scope.$eval() is undefined if both input fields have the same directive如果两个输入字段具有相同的指令,则 scope.$eval() 未定义
【发布时间】:2019-04-18 13:03:23
【问题描述】:

我正在尝试验证两个密码输入字段。只需确认它们相等。 (如果我的方法不对,建议另一种方法

我已经实现了一个带有简单验证的指令,检查“确认”密码是否与原始密码相同。但是该指令还会检查其他内容,因此我需要同时拥有两个输入字段才能拥有它。

问题是,当我在两个输入字段上都有指令时,我无法通过属性读取它们的模型值(以检查它们是否匹配)。

这是一个没有第一个密码指令的工作演示:

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {

});
app.directive('myDir', function() {
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      ctrl.$validators.mismatch = function(modelValue, viewValue) {
        // MAIN CODE:
        return viewValue === scope.$eval(attrs.confirm);
      };

      ctrl.$validators.short = function(modelValue, viewValue) {
        if (ctrl.$isEmpty(modelValue)) {
          return true;
        }
        if (modelValue.length >= 3) {
          return true;
        }
        return false;
      }
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">

  <form name="form1">
    <input type="password" name="password1" ng-model="pass1"><br>
    <input type="password" my-dir confirm="pass1" name="password2" ng-model="pass2"><br>
    <pre>{{form1.password2.$error | json}}</pre>
    <p ng-show="form1.password2.$error.mismatch" style="color:red">Passwords are different</p>
  </form>

</div>

如果我将第一个文件更改为:

<input type="password" my-dir confirm="pass2" name="password1" ng-model="pass1">

要双向验证,则 scope.$eval(attrs.confirm) 变为 undefined 对于两个字段。

这是我的问题的演示:

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {

});
app.directive('myDir', function() {
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      ctrl.$validators.mismatch = function(modelValue, viewValue) {
        // `scope.$eval(attrs.confirm)` always undefined
        return viewValue === scope.$eval(attrs.confirm);
      };

      ctrl.$validators.short = function(modelValue, viewValue) {
        if (ctrl.$isEmpty(modelValue)) {
          return true;
        }
        if (modelValue.length >= 3) {
          return true;
        }
        return false;
      }
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">

  <form name="form1">
    <input type="password" my-dir confirm="pass2" name="password1" ng-model="pass1"><br>
    <input type="password" my-dir confirm="pass1" name="password2" ng-model="pass2"><br>
    <pre>{{form1.password2.$error | json}}</pre>
    <p ng-show="form1.password2.$error.mismatch || form1.password.$error.mismatch" style="color:red">
      Passwords are different
    </p>
  </form>

</div>

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-validation


    【解决方案1】:

    你需要做两件事: 1. 添加ng-model-options="{allowInvalid: true}",这样无效值仍然会更新范围值。 2.现在你有问题,例如更改第二个输入不会触发第一次重新验证。这是使用观察完成的:

      <body ng-controller="MainCtrl" ng-init="x = 0; y = 0">
        <form name="form1">
        <input type="password" my-dir="{{y}}" confirm="pass2" name="password1" ng-model="pass1" ng-model-options="{allowInvalid: true}"
           ng-change="x = x + 1"><br>
        <input type="password" my-dir="{{x}}" confirm="pass1" name="password2" ng-model="pass2" ng-model-options="{allowInvalid: true}"
           ng-change="y = y + 1"><br>
    

    attrs.$observe('myDir', function() {
        ctrl.$validate();
    });
    

    http://plnkr.co/edit/ws4tVWGXfFNR2yqLRJN7?p=preview

    附:对于通常的字段,我会写 my-dir="{{pass1}}" 然后在 $eval 和 ng-change 中不需要,但是对于密码......不确定

    【讨论】:

    • 这实际上让我想到了设置一个观察者并使用$setValidity,而不是使用$validators。我想我仍然可以检查它们是否与return $parse(attrs.confirm)(scope) == ctrl.$modelValue 匹配。但在我和你的解决方案中,感觉就像是 hack
    • 另一种方式可以是:my-dir="{{password1 === password2}}"
    猜你喜欢
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多