使用ng-form进行角度ng-repeat,在控制器中访问验证

时间:2014-06-03 16:39:29

标签: angularjs validation angularjs-ng-repeat angularjs-ng-form

我正在尝试使用ng-repeat生成可编辑列表。我想提醒用户在继续之前更新任何编辑,因此我使用ng-form动态创建“嵌套”表单,因为文档说我可以对这些动态创建的输入使用验证。

虽然这似乎在HTML中起作用,但我没有看到如何在控制器中访问那些动态创建的表单和相关的验证字段。具体来说,当用户更改输入时,我使用表单$ dirty属性调出一个按钮来告诉用户提交更改。到现在为止还挺好。但是,一旦提交了更改,我希望在字段上$setPristine()表示已设置更改。在我允许提交主表单之前,可能还有其他方法可以确保在每个输入上提交更改,但这是我能想到的最好的。

不幸的是,即使文档说如果我将ng-form命名为它将传播到$scope对象,我找不到访问它的方法。 $scope.dynamic_form未定义。

这是一个显示我的意思的傻瓜:

plnk

谢谢!

[编辑]只是为了解决这个问题,这个具体例子的作用是在动态创建的输入上添加ng-click

ng-click="namesForm.name.$setPristine();clean()"

但是我仍然无法访问控制器中动态创建的表单。例如,我想向namesForm.name.$pristine添加观察程序,以便每当子表单为mainForm.$setValidity(false)时我都可以设置$dirty,以防止用户提交主表单,直到已经提交了所有子表单更改。

简而言之,问题是如何在父控制器中访问动态创建的嵌套ngForm的验证值?

1 个答案:

答案 0 :(得分:42)

更新2015-01-17:

Leblanc Meneses在评论 Angular 1.3 中指出,现在支持使用formngForminput指令进行插值。

这意味着使用表达式命名元素:

<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
    <input type="text"
           name="input_{{$index}}_0"></input>
    <!-- ... -->
</div>  

将按预期工作:

$scope['namesForm_0']
$scope.namesForm_1

// Access nested form elements:
$scope.namesForm_1.input_1_0
...

Angular的原始答案&lt; = 1.2:

使用表单和ngFormController很快就会变得棘手。

您需要注意,您可以动态添加表单元素和输入,但它们不能动态命名 - 插值在ngFormname中不起作用指令。

例如,如果您尝试动态命名嵌套表单,请执行以下操作:

<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
    <!-- ... -->
</div>  

您可以只访问带有文字名scope['namesForm_0']的单个(最后一个)表单,而不是在范围内使用所有嵌套表单:scope['namesForm_{{$index}}']

在您的情况下,您需要创建一个自定义指令,该指令将与ngForm一起添加,以处理该表单实例的设置$pristine$$invalid

<强> JavaScript的:

该指令将监视其表单的$dirty状态,以设置$validity以防止在脏时提交,并在按下“清除”按钮时设置$pristine状态。< / p>

app.directive('formCleaner', function(){
    return {
        scope: true,
        require: '^form',
        link: function(scope, element, attr){
            scope.clean = function () {
                scope.namesForm.$setPristine();
            };

            scope.$watch('namesForm.$dirty', function(isDirty){
                scope.namesForm.$setValidity('name', !isDirty);
            });
        }
    };
});

<强> HTML:

然后,对HTML的唯一更改是添加formCleaner指令。

因此,请更改原始HTML:

<body ng-controller="MainCtrl">
    <form name="mainForm" submit="submit()">
        <h3>My Editable List</h3>
        <div ng-form="namesForm"
             ng-repeat="name in names">
            <!-- ... -->
        </div>
        <button class="btn btn-default" type="submit">Submit</button>
    </form>
</body>

,在form-cleaner旁边添加ng-form

<body ng-controller="MainCtrl">
    <form name="mainForm" submit="submit()">
        <h3>My Editable List</h3>

        <!-- Add the `form-cleaner` directive to the element with `ng-form` -->
        <div form-cleaner
             ng-form="namesForm"
             ng-repeat="name in names">
            <!-- ... -->
        </div>
        <button class="btn btn-default" type="submit">Submit</button>
    </form>
</body>

这是一个更新的Plunker,显示了新的行为:http://plnkr.co/edit/Lxem5HJXe0UCvslqbJr3?p=preview