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

更新 2015年 7 月 31日 これは 1.3 以降で修正されています。

元の回答 残念ながら、これは現時点で 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);
}
于 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 に答える