另一个模型更改时验证一个字段

时间:2015-06-09 20:32:00

标签: angularjs

已经存在许多问题,讨论能够根据另一个模型更改的值验证一个字段。其中许多问题似乎都已过时,因为Angular在这些问题发生后发生了变化。

我有一个指令允许用户选择"颜色"。还有其他指令允许用户选择"尺寸" (宽度和高度)。某些颜色仅适用于某些尺寸。

我的颜色"指令有一个额外的指令来管理验证。如果宽度和高度超过一定数量,我添加我的错误信息,一切都很好。

然而,当"尺寸"时,同样的验证不会触发。更改。我试图在大小字段上使用on-change="form.myfield.$validate(),这提供了所需的功能,但是因为该字段变为无效,"颜色" model现在是undefined

当另一个模型的值发生变化时,是否有一种简单的方法可以在字段上触发验证?

这是一个Plunkr。

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

修改

我越是想到这一点,我越相信我意识到由于各种多元素指令之间发生的复杂交互,对这种类型的应用程序的验证将非常困难。我认为根据某些模型值设置各种输入的可接受值可能更简单,从而防止首先选择任何无效值。

2 个答案:

答案 0 :(得分:3)

您可以在widthheight属性上添加监视并有条件地设置颜色输入的有效性。



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

app.controller('MainCtrl', function($scope) {
  $scope.colors = [
    {
      description: 'Red',
      sku: '5555',
      oversize: true
    },
    {
      description: 'Blue',
      sku: '6666',
      oversize: false
    }
  ]
  
});


app.directive('oversize', function(){
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      function validator (modelVal, viewVal) {
        var w = scope.width;
        var h = scope.height;
        var isValid = false;
        if (w > 4 && h > 4) {
          if (modelVal.oversize === true) {
            isValid = true;
          }
        } else {
          isValid = true;
        }
        return isValid;
      
      }
      ctrl.$validators.oversize = validator;
      scope.$watch('width', function () {
        ctrl.$setValidity("oversize", validator(scope.color));
      })
      scope.$watch('height', function () {
        ctrl.$setValidity("oversize", validator(scope.color));
      })
    }
  }
})

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.16/angular.js" data-semver="1.3.16"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <form action="" name="form">
      
      <p>Red is available in oversize, blue is not.</p>
      <p>If both width and height are > 4, blue cannot be used</p>
      
      <div ng-show="form.color.$error.oversize">That is not available in this size</div>
      
      Color
      <select oversize name="color" ng-model="$parent.color" ng-options="c.description for c in colors track by c.sku"></select>
      
      <br>
      
      Width
      <select name="width" ng-model="width" ng-options="v for v in [1,2,3,4,5]"></select>
      <br>
      
      Height
      <select name="height" ng-model="height" ng-options="v for v in [1,2,3,4,5]" id=""></select>    
    </form>
    
    <p>Oversize for {{color.description}} is {{color.oversize}}</p>

  </body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这不应该是一个单独的答案,因为99%的答案来自ShankarSangoli的答案,它可能不再与OP相关,但希望这将有助于其他人。未定义颜色模型的值的问题是由验证引起的。如果验证失败,Angular Validations会将模型设置为undefined(请参阅$ validate部分)。如果使用ng-model-options="{ allowInvalid: true }"装饰颜色的选择标记,则验证将允许将值保存到模型中。这里的一个重要问题是它将保存到您的模型中,任何提交操作都将使用此无效数据。当存在任何验证错误时,请小心限制页面提交,并且你应该都很好。

同样,这不应该是一个单独的答案,但我没有足够的代表发表评论。 ShankarSangoli的回答应该得到大部分的信用。如果没有它,我将无法做到这一点。

&#13;
&#13;
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.colors = [
    {
      description: 'Red',
      sku: '5555',
      oversize: true
    },
    {
      description: 'Blue',
      sku: '6666',
      oversize: false
    }
  ]
  
});


app.directive('oversize', function(){
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      function validator (modelVal, viewVal) {
        var w = scope.width;
        var h = scope.height;
        var isValid = false;
        if (w > 4 && h > 4) {
          if (modelVal.oversize === true) {
            isValid = true;
          }
        } else {
          isValid = true;
        }
        return isValid;
      
      }
      ctrl.$validators.oversize = validator;
      scope.$watch('width', function () {
        ctrl.$setValidity("oversize", validator(scope.color));
      })
      scope.$watch('height', function () {
        ctrl.$setValidity("oversize", validator(scope.color));
      })
    }
  }
})
&#13;
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.16/angular.js" data-semver="1.3.16"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <form action="" name="form">
      
      <p>Red is available in oversize, blue is not.</p>
      <p>If both width and height are > 4, blue cannot be used</p>
      
      <div ng-show="form.color.$error.oversize">That is not available in this size</div>
      
      Color
      <select oversize name="color" ng-model="$parent.color" ng-options="c.description for c in colors track by c.sku" ng-model-options="{ allowInvalid: true }" ></select>
      
      <br>
      
      Width
      <select name="width" ng-model="width" ng-options="v for v in [1,2,3,4,5]" ></select>
      <br>
      
      Height
      <select name="height" ng-model="height" ng-options="v for v in [1,2,3,4,5]" ></select>    
    </form>
    
    <p>Oversize for {{color.description}} is {{color.oversize}}</p>

  </body>

</html>
&#13;
&#13;
&#13;