_ng-repeat
_を使用して編集可能なリストを生成しようとしています。先に進む前に編集内容を更新するようユーザーに思い出させたいので、ドキュメントでこれらの動的に作成された入力で検証を使用できると書かれているので、_ng-form
_を使用してその場で「ネスト」フォームを作成しています。
これはHTML内で機能するように見えますが、コントローラーで動的に作成されたフォームと関連する検証フィールドにアクセスする方法がわかりません。具体的には、ユーザーが入力を変更する場合、フォームの$ dirtyプロパティを使用して、変更をコミットするようユーザーに指示するボタンを表示します。ここまでは順調ですね。ただし、変更がコミットされたら、フィールドで$setPristine()
を使用して、変更が設定されたことを示します。メインフォームのコミットを許可する前に、各入力で変更をコミットすることを保証する他の方法があるかもしれませんが、これは私が思いつく最高のものでした。
残念ながら、ドキュメントではng-formに名前を付けると_$scope
_オブジェクトに伝播されると書かれていますが、それにアクセスする方法が見つかりません。 _$scope.dynamic_form
_は未定義です。
ここに私が意味することを示すプランカーがあります:
ありがとう!
[編集]問題に追加するために、この特定の例で機能するのは、動的に作成された入力の_ng-click
_に追加することです。
_ng-click="namesForm.name.$setPristine();clean()"
_
しかし、コントローラーで動的に作成されたフォームにはまだアクセスできません。たとえば、サブフォームが_namesForm.name.$pristine
_である場合は常にmainForm.$setValidity(false)
を設定できるように_$dirty
_にウォッチャーを追加して、ユーザーがメインを送信できないようにしますすべてのサブフォームの変更がコミットされるまでフォーム。
簡単に言えば、問題は、動的に作成されたネストされたngFormの検証値に親コントローラーでアクセスする方法ですか?
2015-01-17に更新:
Leblanc Menesesがコメントで指摘したようにAngular 1.3はform
、ngForm
およびinput
ディレクティブ。
これは、式を使用して要素に名前を付けることを意味します。
<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 <= 1.2:の元の答え
フォームとngFormController
を使用すると、かなりすぐにトリッキーになります。
フォーム要素と入力を動的に追加できるが、動的に名前を付けることはできないことに注意する必要がありますnamed-ngForm
またはname
ディレクティブ。
たとえば、次のようにネストされたフォームに動的に名前を付けようとした場合:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<!-- ... -->
</div>
次のようなスコープですべてのネストされたフォームを使用可能にする代わりに:scope['namesForm_0']
リテラル名scope['namesForm_{{$index}}']
を持つ単一の(最後の)フォームにのみアクセスできます。
あなたの状況では、そのフォームインスタンスの$pristine$
と$invalid
の設定を処理するためにngForm
とともに追加されるカスタムディレクティブを作成する必要があります。
JavaScript:
このディレクティブは、フォームの$dirty
状態を監視して$validity
を設定し、ダーティな場合の送信を防止し、 'clean'ボタンが押された場合の$pristine
状態の設定を処理します。
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