如何在angularjs表单中添加数组大小验证规则?

时间:2014-03-04 15:43:58

标签: javascript forms angularjs validation angularjs-directive

我有一个表单,其中包含一些文本输入字段和存储在控制器$ scope中的项目的动态列表,其中包含一些添加/删除列表中项目的功能。 我想使表单无效,直到项目列表达到预定义的长度。

所以我创建了一个formRepeat指令,该指令接受ngModel属性,然后使用ngModelController使表单无效。

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

这有效,但我认为这不是更好的方法,因为指令不是很灵活。

最简单的方法是使控制器中的表单无效:

$scope.myForm.$valid = false;

但这不起作用。

有更好的方法吗?

7 个答案:

答案 0 :(得分:8)

对我来说最简单的方法是将数组的长度定位为隐藏号码input并对其进行min验证。事实上非常干净的解决方案。

<input style="display: none;" type="number" name="itemsCount" ng-model="items.length" min="{{min}}">

查看updated plunker

答案 1 :(得分:3)

根据您的plunker。我将使用以下$watch函数(类似于@NicolasMoise响应)

$scope.$watch('items', function (items) {
    $scope.myForm.$setValidity('count', items.length >= 5);
}, true);

objectEquality标记设置为true非常重要,这样如果任何对象属性发生变化,$watch将会触发

或者,如果仅进行浅层列表(集合)比较,请使用$watchCollection

$scope.$watchCollection('items', function (items) {
    $scope.myForm.$setValidity('count', items.length >= 5);
});

我也从来没有跟$setValidity('$valid')或类似的

运气好

答案 2 :(得分:3)

最好的方法(IMO)是创建一个使用ngModelController Validators的自定义指令。

验证程序在每次模型更新时执行,并用于表单有效性。 您的指令可能如下所示:

angular.module('directiveTest', []).directive('minLength', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ngModel) {
  scope.minlength = attrs.minLength || 1;
  ngModel.$validators.minLength  = function(modelValue){
    /* Assume TRUE when empty, as ngRequired should be used for mandatory values */
    return (ngModel.$isEmpty(modelValue)) ? true : (modelValue.length >= scope.minlength);
  };
}
};
});

可以从你的HTML中调用它:

<input type="text" name="content" ng-list min-length="2" ng-model="content" />

您可以在以下Plunker找到工作示例。

答案 3 :(得分:1)

在这种情况下,我认为没有必要使用指令。只需对项目进行ng-repeat,然后在控制器内进行此类

$scope.$watch('items', function(val){
    if(val.length<5){
        //$scope.myForm should be available here
        $scope.myForm.setValidity('$valid');
        //add additional form validation ($dirty, setting back to $invalid, etc...)
    }
})

答案 4 :(得分:0)

答案 5 :(得分:0)

我认为你可以使用ng-class实现这一目标。

试试这个, 在HTML中,

<html data-ng-app="myApp">

  <head>
    <link data-require="bootstrap-css@*" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <script data-require="angular.js@*" data-semver="1.2.13" src="http://code.angularjs.org/1.2.13/angular.js"></script>
    <script data-require="angular-animate@*" data-semver="1.2.13" src="http://code.angularjs.org/1.2.13/angular-animate.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body data-ng-controller="MainCtrl">
    <div class="container">
      <div class="col-sm-12 col-md-6 col-md-offset-3">
        <form name="myForm" ng-class="formClass">
          <div class="form-group">
            <label>Name</label>
            <input type="text" name="name" data-ng-model="user.name" class="form-control" required="" />
          </div>
          <div class="form-group">
            <label>Country</label>
            <input type="text" name="country" data-ng-model="user.country" class="form-control" required="" />
          </div>
          <div class="form-group">
            <label>Items</label>
            <br />
            <button type="button" class="btn btn-primary" data-ng-click="addItem()">Add</button>
            <p data-ng-show="items.length < min">I need at least {{min}} items ! (so {{min - items.length}} more would be good)</p>
            <div data-ng-repeat="item in items">
              <button type="button" class="btn btn-danger" data-ng-click="removeItem($index)">Delete</button>
              <span>{{item}}</span>
            </div>
          </div>
        </form>
      </div>
    </div>
  </body>

</html>

在你的script.js中,

angular.module('myApp', ['ngAnimate']);

angular.module('myApp')
  .controller('MainCtrl', ['$scope', function ($scope) {
    $scope.items = [];
    $scope.min = 5;
    var _counter = 0;
     $scope.formClass="invalid";
    $scope.addItem = function () {
      $scope.items.push('item' + _counter);
      _counter++;
     $scope.isFormValid();
    };
    $scope.isFormValid=function(){
       if ($scope.items.length < 5) {
        $scope.formClass="invalid";
      } 
      else if ($scope.items.length >=5){
         $scope.formClass="valid";
      }
    }
    $scope.removeItem = function (index) {
      $scope.items.splice(index, 1);  
      $scope.isFormValid();
    };

  }]);

在css文件中,

body {
  padding: 16px;
  background: #555555;
}

/*.my-form {
  transition:0.5s linear all;
  padding: 16px;
  border-radius: 4px;
  background: #ffffea;
}*/

.invalid {
    transition:0.5s linear all;
  padding: 16px;
  border-radius: 4px;
  background: #ffffea;
  background: #ffeaea;
}

.valid {
    transition:0.5s linear all;
  padding: 16px;
  border-radius: 4px;
  background: #ffffea;
  background: #eaffea;
}

你想要这样的东西吗?。

请查看此plunker

答案 6 :(得分:0)

有点晚了,但我这样做:

<button type="button" class="btn btn-success" 
        ng-disabled="form.$invalid || user.groups.length == 0>
        Submit
</button>