AngularJS与NG-重复验证多种形式多种、形式、AngularJS、NG

由网友(强颜欢笑)分享简介:我使用的NG-窗体作为父窗体和子毫克形式与NG重复验证。I am using ng-form as a parent form and child mg-forms for validation with ng-repeat.
我使用的NG-窗体作为父窗体和子毫克形式与NG重复验证。

I am using ng-form as a parent form and child mg-forms for validation with ng-repeat.

<div ng-form="form">
    <div ng-repeat="field in fields">
        <div ng-form="subform"><input...></div>
    </div>
</div>

和验证是这样的:

if ($scope.form.subform.$invalid && !$scope.form.subform.$error.required) {
    // Do something...
}

(这是很简单的例子,我有不同的输入类型和名称不同,例如输入[文]被命名为TextForm多个不同的子表单,输入[数字]被NumericForm等)

(this is very simplified example, I have more different subforms for different input types and with different names, e.g. input[text] is named as a TextForm, input[numeric] is NumericForm etc.)

一切正常,如果只有在字段如预期。但是,如果NG-重复生成多个领域,验证只触发最后一个子窗体,其他被忽略。

Everything works as expected if there is only on field. But if ng-repeat generates multiple fields, validation triggers only the last subform, others gets ignored.

有没有通过所有的子表单骑自行车的方式来检查,如果其中有一个是无效的?

Is there a way of cycling through all subforms to check if one of them is invalid?

此外,我喜欢打这一切空缺必填字段:

Also, I am marking all unfilled required fields like this:

if ($scope.form.$error.required) {
     angular.forEach($scope.form.$error.required,
         function (object, index) {
             $scope.form.$error.required[index].$setDirty();
         }
     );
}

所以,如果我的领域都是这样完成的:

So if my fields are done like this:

....ng-form="TextForm" ng-class="{ 'has-error': TextForm.$dirty && TextForm.$invalid }"....

和它标志着即便有许多具有相同名称的相同的子窗体全部

And it marks all the subforms even if there are many of the same ones with the same name.

也许我可以做无效域相似的地方?虽然尝试了很多事情,没有什么工作......

Maybe I could do something similar with invalid fields? Though tried many things, nothing worked...

推荐答案

针对此解决方案是创建了 ngModelController 的错误分配给一个变​​量指令每个 NG-重复输入。

A solution for this is to create a directive that assigns the ngModelController's error to a variable in each ng-repeat input.

下面是一个可能的实现让每个子窗体的错误。 演示

Below is a possible implementation to get the errors of each subForm. DEMO

JAVASCRIPT(指令)

  .directive('ngModelError', function($parse, $timeout) {
    return {
      require: ['ngModel', 'form'],
      link: function(scope, elem, attr, ctrls) {
        var ngModel = ctrls[0],
            ngForm = ctrls[1],
            fieldGet = $parse(attr.ngModelError),
            fieldSet = fieldGet.assign,
            field = fieldGet(scope);

        $timeout(function() {
          field.$error = ngModel.$error;
          field.ngForm = ngForm;
          fieldSet(scope, field);
        });

      }
    };
  });

HTML

<form name="form" ng-submit="submit(form, fields)" novalidate>
  <div ng-form="subForm" ng-repeat="field in fields"
    ng-class="{'has-error': subForm.$invalid && form.$dirty}">
    <label class="control-label">{{field.label}}</label>
    <input type="{{field.type}}" placeholder="{{field.placeholder}}" 
      ng-model="field.model" name="field" 
      ng-required="field.isRequired" class="form-control" 
      ng-model-error="field" />
  </div>
  <br>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

JAVASCRIPT(控制器)

请注意该领域是如何结构:

Please take note how the fields are structure:

  .controller('Ctrl', function($scope) {
    $scope.fields = {
      email: {
        type: 'email',
        placeholder: 'Enter email',
        isRequired: true,
        label: 'Email Address'
      }, 

      password: {
        type: 'password',
        placeholder: 'Enter password',
        isRequired: true,
        label: 'Password'
      }
    };

    $scope.submit = function(form, fields) {
      form.$dirty = true;

      if(form.$valid) {
        // do whatever
      } else {
        // accessing ngForm for email field
        console.log(fields.email.ngForm);
        // accessing errors for email field
        console.log(fields.email.$error);

        // accessing ngForm for password field
        console.log(fields.password.ngForm);
        // accessing errors for password field
        console.log(fields.password.$error);
      }
    };
  })