29

我在 AngularJS 中有以下静态表单:

<form name="myForm" class="form-horizontal">

  <label>First Name:</label>
  <input type="text" name="first_name" ng-model="entity.first_name">

  <label>Last Name:</label>
  <input type="text" name="last_name" ng-model="entity.last_name">

</form>

Angular 为我创建了一个 FormController 并将其发布到范围内(在表单名称下)。这意味着我可以访问以下属性:

$scope.myForm.first_name.$error
$scope.myForm.last_name.$invalid
...

这个超级好用!

但就我而言,我正在使用指令动态构建表单:

<form name="myForm" class="form-horizontal">

  <field which="first_name"></field>
  <field which="last_name"></field>

</form>

<field>指令直到一段时间后才会解析为实际元素(<input>在我从服务器获取一些数据、链接指令等之后)。

这里的问题是表单控制器上没有定义任何字段属性,就好像动态字段没有向 FormController 注册一样:

// The following properties are UNDEFINED (but $scope.myForm exists)
$scope.myForm.first_name
$scope.myForm.last_name

知道为什么吗?任何解决方案/解决方法?

您可以在这个 jsFiddle 中看到整个代码:http:
//jsfiddle.net/vincedo/3wcYV/

4

2 回答 2

25

更新 7/31/2015自 1.3 以来已修复此问题,请参见此处:https ://github.com/angular/angular.js/issues/1404#issuecomment-125805732

原始答案 不幸的是,目前这是 AngularJS 的短板。Angular 的表单验证不适用于动态命名的字段。您可以在 HTML 底部添加以下内容,以准确查看发生了什么:

<pre>{{myForm|json}}</pre>

如您所见,Angular 没有正确获取动态输入名称。目前有一个涉及嵌套表单的解决方法可能会有点讨厌,但它确实有效并且(需要一些额外的工作)将毫无问题地提交父表单。

如果您愿意,可以为该问题争取更多支持:GitHub 问题 - 动态元素验证。无论哪种方式,这是代码:

http://jsfiddle.net/langdonx/6H8Xx/2/

HTML:

<div data-ng-app>
    <div data-ng-controller="MyController">
        <form id="my_form" name="my_form" action="/echo/jsonp/" method="get">
            <div data-ng-repeat="field in form.data.fields">
                <ng-form name="form">
                    <label for="{{ field.name }}">{{ field.label }}:</label>
                    <input type="text" id="{{ field.name }}" name="{{field.name}}" data-ng-model="field.data" required>
                    <div class="validation_error" data-ng-show="form['\{\{field.name\}\}'].$error.required">Can't be empty.</div>

                </ng-form>
            </div>
            <input type="submit" />
        </form>
    </div>
</div>

JavaScript:

MyController.$inject = ["$scope"];

function MyController($scope) {
    $scope.form = {};
    $scope.form.data = {};
    $scope.form.data.fields = []

    var f1 = {
        "name": "input_1",
        "label": "My Label 1",
        "data": ""
    };
    var f2 = {
        "name": "input_2",
        "label": "My Label 2",
        "data": ""
    };

    $scope.form.data.fields.push(f1);
    $scope.form.data.fields.push(f2);
}
于 2013-04-06T04:16:08.830 回答
2

我自己也遇到了类似的问题,我解决这个问题的方法是在模板上调用 $compile 之前放置字段的名称。一个简单的 string.replace 就可以了。再说一遍,这只是可能的,因为我通过 http 获取字段模板并可以访问模板文本。

更新:这里有一个小技巧,可以使您的示例正常工作

app.directive('field', function($compile) {
    var linker= function(scope, element){

    var template = '<input type="text" name="{{fname}}" ng-model="model">'
    .replace('{{fname}}', scope.fname);
        element.html(template)
        $compile(element.contents())(scope)
    }
  return {
    restrict: 'E',
    scope: {
      fname: '=',
      model: '='
    },

    replace: true,
      link: linker
  };
});

http://jsfiddle.net/2Ljgfsg9/4/

于 2014-10-14T15:53:06.037 回答