web-dev-qa-db-ja.com

AngularJS:動的に追加されたフィールドがFormControllerに登録されない

AngularJSに次のstatic形式があります:

<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/

29
AngularChef

Update 7/31/2015これは1.3以降で修正されています。以下を参照してください: https://github.com/angular/angular。 js/issues/1404#issuecomment-125805732

元の回答残念ながら、これは現時点でのAngularJSの短編です。 Angularのフォーム検証は、動的に名前が付けられたフィールドでは機能しません。 HTMLの下部に以下を追加して、何が起こっているかを正確に確認できます。

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

ご覧のように、Angularは動的入力名を正しく取得していません。現在、入れ子になったフォームに関連する回避策があります。仕事)親フォームを問題なく提出します。

必要に応じて、問題のサポートをさらに増やすことができます: GitHub Issue-dynamic element validation 。いずれにせよ、ここにコードがあります:

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

私自身も同様の問題に遭遇し、それを回避するためにテンプレートで$ 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/

2
Oliv312