简体   繁体   English

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

[英]How to add an array size validation rule in an angularjs form?

I have a form with some text input fields and a dynamic list of items stored in the $scope of the controller, with some functions to add/remove items in the list. 我有一个表单,其中包含一些文本输入字段和存储在控制器的$ scope中的项目的动态列表,其中一些函数用于添加/删除列表中的项目。 I want to invalidate the form until the items list reaches a predefined length. 我想使表单无效,直到项目列表达到预定义的长度。

So I created a formRepeat directive which takes a ngModel attribute and then use the ngModelController to invalidate the form. 所以我创建了一个formRepeat指令,该指令接受ngModel属性,然后使用ngModelController使表单无效。

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

This works but I think it's not the better way to do that as the directive is not very flexible. 这有效,但我认为这不是更好的方法,因为指令不是很灵活。

The easiest would be to invalidate the form in the controller with something like : 最简单的方法是使控制器中的表单无效:

$scope.myForm.$valid = false;

But this doesn't work. 但这不起作用。

Is there a better way ? 有没有更好的办法 ?

The easiest way for me was to target array's length as hidden number input and put min validation on it. 对我来说最简单的方法是将数组的长度作为隐藏数字input并对其进行min验证。 Very clean solution, in fact. 事实上,非常干净的解决方案。

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

Check out the updated plunker 查看更新的plunker

Based upon your plunker . 基于你的plunker I'd use the following $watch function (similar to @NicolasMoise response) 我使用以下$watch函数(类似于@NicolasMoise响应)

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

It's important to set the objectEquality flag to true so that the $watch will fire if any of the objects properties change objectEquality标志设置为true非常重要,以便在任何对象属性发生更改时触发$watch

or, if only a shallow list (collection) comparison is made, use $watchCollection 或者,如果只进行浅层列表(集合)比较,请使用$watchCollection

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

I've also never had any luck with $setValidity('$valid') or similar 我也没有运气$setValidity('$valid')或类似的

The best way to do so (IMO) is to create a custom directive that uses the ngModelController Validators . 最好的方法(IMO)是创建一个使用ngModelController验证器的自定义指令。

Validators get executed every time there is an update on the model and are used for form validity. 验证器每次在模型上有更新时都会执行,并用于表单有效性。 Your directive may look something like this: 您的指令可能如下所示:

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);
  };
}
};
});

And can call it from your HTML like this: 并且可以从您的HTML中调用它,如下所示:

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

You can find the working example on the following Plunker . 您可以在以下Plunker上找到工作示例。

I don't think it's necessary to use a directive in this case. 在这种情况下,我认为没有必要使用指令。 Just have an ng-repeat for items and inside your controller something like this 只需对项目进行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...)
    }
})

I think you can achieve this using ng-class. 我认为你可以使用ng-class实现这一目标。

Try this , In HTML, 试试这个,在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>

In your script.js, 在你的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();
    };

  }]);

In css file, 在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;
}

Do you want something like this?. 你想要这样的东西吗?

Please have a look at this plunker 请看看这个plunker

a bit late, but I do that like this: 有点晚了,但我这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM