简体   繁体   English

使用ngRepeat在Angular中进行分组验证

[英]Grouped validation in Angular with ngRepeat

I have a large form that I have splitted into tabs. 我有一个大表单,我已分成标签。 Each tab contains multiple different input fields with validation on the inputs. 每个选项卡包含多个不同的输入字段,并对输入进行验证。 Right now I only have validation per input field, but I'm now trying to add validation per tab. 现在我只对每个输入字段进行验证,但我现在正在尝试为每个选项卡添加验证。 That is, I want the tabs to indicate if any of its input field contains validation errors. 也就是说,我希望选项卡指示其输入字段是否包含验证错误。

The form is rendered using ngRepeat: 表单使用ngRepeat呈现:

<form name="createForm" novalidate>
  <ul class="nav nav-tabs">
    <li ng-repeat="tab in tabs" ng-class="{active: $index == 0}">
      <a ng-hide="tab.isValid" data-target="#tab{{$index + 1}}" data-toggle="tab" class="invalid">{{tab.title}}</a>
      <a ng-show="tab.isValid" data-target="#tab{{$index + 1}}" data-toggle="tab">{{tab.title}}</a>
    </li>
  </ul>

  <div class="tab-content">
    <div class="tab-pane fade in" id="tab{{$index + 1}}" ng-repeat="tab in tabs" ng-class="{active: $index == 0}">
      <div ng-include="'/view/create/partials/' + tab.content"></div>
    </div>
  </div>
</form>

The array of tabs: 标签数组:

$scope.tabs = [
  { title: "Tab1", content: 'tab1.html', isValid: true },
  { title: "Tab2", content: "tab2.html", isValid: true },
  { title: "Tab3", content: "tab3.html", isValid: true }];

The HTML for each tab: 每个标签的HTML:

<label for="age">Age</label>
<input type="text" class="form-control" ng-model="person.tab1.Age" name="Age" maxlength="3" data-integer />

<label for="height">Height</label>
<input type="text" class="form-control" ng-model="person.tab1.Height" name="Height" data-float />

The 'data-integer' and 'data-float' are custom validation directives: 'data-integer'和'data-float'是自定义验证指令:

var INTEGER_REGEXP = /^\d*$/;
app.directive('integer', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (INTEGER_REGEXP.test(viewValue)) {
                    ctrl.$setValidity('integer', true);
                    return parseInt(viewValue);
                } else {
                    ctrl.$setValidity('integer', false);
                    return undefined;
                }
            });
        }
    };
});

My idea is to set the 'isValid' variable to false if any of its child input fields are invalid. 我的想法是,如果任何子输入字段无效,则将'isValid'变量设置为false。 I'm not sure where to execute this function or how this function would look like. 我不确定在哪里执行此函数或此函数的外观如何。 I'm also very welcome for ideas on improvement or other ways to do this. 我也非常欢迎有关改进的想法或其他方法。

You group validation by using a form, so in a simple scenario each tab would have a separate form. 您可以使用表单对验证进行分组,因此在一个简单的场景中,每个选项卡都有一个单独的表单。 However, I understand you want to have a root form for handling the submission, but group tab fields together to give a finer-grained UI response to validation. 但是,我知道您希望有一个根表单来处理提交,但是将选项卡字段组合在一起,以便为验证提供更细粒度的UI响应。

In that case, you can use nested forms. 在这种情况下,您可以使用嵌套表单。 See this example for more information . 有关更多信息,请参阅此示例 You'll have a root form (named, of course) and then declare additional ng-form for each group within it. 您将拥有一个根form (当然命名),然后为其中的每个组声明其他ng-form Note that you must use the ng-form directive specifically for the nested forms because browsers won't let you nest form tags; 请注意,您必须专门为嵌套表单使用ng-form指令,因为浏览器不允许您嵌套form标记; ng-form directive as an element works around that. ng-form指令作为一个元素可以解决这个问题。

For you, this means you'd keep your parent form as is. 对您而言,这意味着您将保留您的父表格。 Then you just wrap the fields in each tab with their own ng-form directive, giving each a unique name representing each tab. 然后,您只需使用自己的ng-form指令将每个选项卡中的字段包装起来,为每个选项卡指定每个选项卡的唯一名称。 The validity of each tab will be reflected in the root form ( createForm ) so you can still check if the form is valid overall using the typical approaches eg createForm.$invalid , etc. However, you can now check the state of the nested forms, too eg createForm.Tab1Form.$valid . 每个选项卡的有效性将反映在根表单( createForm )中,因此您仍然可以使用典型方法检查表单是否有效,例如createForm.$invalid等。但是,您现在可以检查嵌套表单的状态,例如createForm.Tab1Form.$valid

The only catch here is that ng-form does not evaluate the name attribute, it uses the literal value, so you'll have troubles generating that name dynamically from the tab.title like you probably want to do. 这里唯一的问题是ng-form不会评估name属性,它会使用文字值,因此您可能会tab.titletab.title一样动态生成该名称的tab.title就像您可能想要做的那样。 I got around that by giving them a literal name in the template. 我通过在模板中给出一个文字名称来解决这个问题。

<form name="createForm" novalidate="">
  <ul class="nav nav-tabs">
    <li ng-repeat="tab in tabs" ng-class="{active: $index == 0}">
      <a data-target="#tab{{$index + 1}}" data-toggle="tab" ng-class="{'invalid': createForm.{{tab.title}}.$invalid}">{{tab.title}}</a>
    </li>
  </ul>
  <div class="tab-content">
    <div class="tab-pane fade in" id="tab{{$index + 1}}" ng-repeat="tab in tabs" ng-class="{active: $index == 0}">

        <div ng-include="tab.content"></div>

    </div>
  </div>
</form>

Here's the plunk . 这是插件

You'll notice that the tab titles are red if the tab's nested form is invalid (type a value into Field 1 and you'll see the validation error class go away). 如果选项卡的嵌套表单无效,您会注意到选项卡标题为红色(在字段1中键入值,您将看到验证错误类消失)。 Note that I didn't wire up your Bootstrap JavaScript behaviors in the demo because I'm lazy, but I believe I've illustrated the point. 请注意,我没有在演示中连接你的Bootstrap JavaScript行为,因为我很懒,但我相信我已经说明了这一点。

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

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