コントローラーのフォームにアクセスできますか?


152

現在以下を使用しています。

$scope.$$childHead.customerForm[firstName]、 そのため:

<form name="customerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" 
         tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

ただし、これはChromeでのみ機能します。今私は以下を試しました:

$scope.editCustomerForm[firstName]、 そのため:

<form name="customerForm" ng-model="editCustomerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

うまくいきません。フォームがFoundationタブ内にあることに注意してください。どうすればアクセスできますfirstNameか?

編集:それは財団タブ内にあるときformはに追加されていないようscopeです。

誰かがこれに対する解決策を持っていますか?

回答:


210

他のコメントでほのめかしたが、 "Controller As"構文を使用する人のために少し詳しく説明すると思いました。

<div ng-controller="MyController as ctrl">

<form name="ctrl.myForm">
    ...inputs
    Dirty? {{ctrl.myForm.$dirty}}

    <button ng-click="ctrl.saveChanges()">Save</button>
</form>

</div>

その後、次のようなコードでFormControllerにアクセスできます。

function MyController () {
    var vm = this;
    vm.saveChanges = saveChanges;

    function saveChanges() {

       if(vm.myForm.$valid) { 
            // Save to db or whatever.
            vm.myForm.$setPristine();
       }
}

私が見る限り、テンプレートは "saveChanges"メソッドを呼び出すことができません。テンプレートに公開されていないためです
Spock

2
「saveChanges」メソッドはJavaScriptの3行目で公開されていますか、それとも誤解していますか?
slopapa 2014

3
それはあなたが私の意見ではクリーナーです全体$スコープ、注入避けることができる手段として、これは良いです
72GM

2
これをジャスミンでどのようにテストしますか?私の仕様では、vm.myFormは未定義
bahrieinn '20

1
これは、コンポーネントとes6を実行する方法である1.5.Xの公式ドキュメントに記載されています。ありがとうございました
MatanCo 2016年

91

親コントローラーで定義されているオブジェクトにフォームを添付できます。その後、子スコープからでもフォームに到達できます。

親コントローラー

$scope.forms = {};

子スコープ内のいくつかのテンプレート

<form name="forms.form1">
</form>

問題は、コントローラーのコードを実行するときにフォームを定義する必要がないことです。だからあなたはこのようなことをしなければなりません

$scope.$watch('forms.form1', function(form) {
  if(form) {
    // your code...
  }
});

10
var watcher = $scope.$watcherifステートメント内で、watcher()を実行してウォッチのバインドを解除することをお勧めします。これにより、1回限りのウォッチになるため、設定後にすべてのダイジェストを見るわけではありません
willJk

91

検証のためにフォームをコントローラーに渡す場合は、送信を処理するメソッドの引数としてフォームを単に渡すことができます。フォーム名を使用するので、元の質問の場合は次のようになります。

<button ng-click="submit(customerForm)">Save</button>

13
将来の読者のために明確にするために、フォームがこれ<form name="myform"></form>に似た名前で定義されているとすると<div ng-form name="myform"></div>、クリックイベントは次のようになりますng-click="submit(myform)"。そして、あなたは次のようにあなたのクリック機能に角度フォームオブジェクトにアクセスすることができます$scope.submit = function (form) { if (form.$valid) {など
マティJ

ここで問題が見つかりました-フォームにドロップダウンリストがあるとします。上記の方法を使用すると、ビューの値のみが得られ、必要な正確な値は得られません。それとも私は何か悪いことをしていますか、フィドルを追加します。
swateek 2016

82

答えに少し遅れましたが、次のオプションが付いていました。それは私のために働いていますが、それが正しい方法であるかどうかはわかりません。

私の見解では、私はこれをやっています:

<form name="formName">
    <div ng-init="setForm(formName);"></div>
</form>

そしてコントローラーで:

$scope.setForm = function (form) {
    $scope.myForm = form;
}

これを行った後、コントローラー変数にフォームが表示されます。 $scope.myForm


1
これに追加する唯一のことは、これがフォームの下部にあることを確認することです。
smb 2014

<div ng-init = "setForm(formName);"> </ div>の位置は関係ありません。アンダーフォームになるように注意してください。
waqas 2014

1
良いですが、私はより単純なソリューションを好みます:ng-init = "$ parent.myForm = formName"コントローラーを変更する必要はありません注:上記のソリューションとは対照的に、直接コントローラーでのみ機能します
mastilver '18

他の方法を試した後、name属性を希望どおりにすることができるので、この方法に落ち着きました。他のダミーオブジェクトソリューションの問題は、このコンポーネントがng-formを持つ別のコンポーネントで使用されている場合、他のng-formがこのフォーム名を文字通り使用することです。したがって、「dummy.myForm」という文字列リテラル(ネストされたプロパティではない)名のフィールドが含まれますが、これは受け入れられません。
バジル2017

私は何度もcontrollerAs構文を使用しようとして失敗しました($ mdDialogで作業しています)。最後にこれで解決し、素晴らしい仕事をしました。唯一の注意点は、コントローラーが最初に実行されたときにはフォームが使用できないため、$ timeoutでコントローラーの初期化を実行する必要があることです
Peter Nixey

22

コントローラのフォームにアクセスできるようにするには、ダミーのスコープオブジェクトにフォームを追加する必要があります。

何かのようなもの $scope.dummy = {}

あなたの状況では、これは次のようなことを意味します:

<form name="dummy.customerForm">

コントローラでは、次の方法でフォームにアクセスできます。

$scope.dummy.customerForm

あなたは次のようなことができるようになります

$scope.dummy.customerForm.$setPristine()

WIKI LINK

「。」モデル内で、プロトタイプの継承が機能していることを確認します。したがって、では<input type="text" ng-model="someObj.prop1">なく<input type="text" ng-model="prop1">

プリミティブを本当に使用したい/必要な場合は、2つの回避策があります。

1.子スコープで$ parent.parentScopePropertyを使用します。これにより、子スコープが独自のプロパティを作成できなくなります。2.親スコープで関数を定義し、子から呼び出し、プリミティブ値を親に渡します(常に可能とは限りません)。


フォームバインディングを定義するための有効領域はどこですか?
Gus Crawford

フォーム要素がdummy.customerForm条件付きである場合に条件ng-ifが満たされるまで定義されないことに言及する価値がありng-ifます
haxxxton

22

この答えは少し遅いですが、すべてをもっと簡単にするソリューションに偶然出会いました。

controllerAs構文を使用している場合は、実際にフォーム名を直接コントローラーに割り当てて、「this」変数から参照できます。これが私のコードでどのようにしたかです:

私はui-routerを介してコントローラーを構成しました(ただし、HTMLでものように直接、好きなように実行できます<div ng-controller="someController as myCtrl">)これは、ui-router構成で次のように表示される可能性があります。

views: {
            "": {
                templateUrl: "someTemplate.html",
                controller: "someController",
                controllerAs: "myCtrl"
            }
       }

そして、HTMLでフォーム名を "controllerAs"。 "name"として設定します。

<ng-form name="myCtrl.someForm">
    <!-- example form code here -->
    <input name="firstName" ng-model="myCtrl.user.firstName" required>
</ng-form>

コントローラ内で、これを非常に簡単に行うことができます:

angular
.module("something")
.controller("someController",
    [
       "$scope",
        function ($scope) {
            var vm = this;
            if(vm.someForm.$valid){
              // do something
            }
    }]);

2
これは他のいくつかの回答が示唆するのとほとんど同じ手法ですが、特に誰もがとにかくコントローラを使用しているため、これは最良のバリエーションであり、受け入れられる回答になるはずです。
セミコロン

6

はい、コントローラのフォームにアクセスできます(docsに記載されています)。

フォームがコントローラースコープで定義されておらず、代わりに子スコープで定義されている場合を除きます。

基本的にng-ifng-repeatng-include、などのいくつかの角度ディレクティブは、孤立した子スコープを作成します。scope: {}プロパティが定義されたカスタムディレクティブも同様です。おそらく、基盤コンポーネントも邪魔になっています。

タグのng-if周りにシンプルを導入するときにも同じ問題がありました<form>

詳細については、以下を参照してください。

注:質問を書き直すことをお勧めします。あなたの質問への答えはイエスですが、あなたの問題は少し異なります:

コントローラーから子スコープのフォームにアクセスできますか?

答えは単純にそうなります:いいえ


... @ondrsの回答($scope.forms = {}and を使用name="forms.form1")で説明されているようにフォームとコントローラを設定しない限り
marapet

KhalilRavannaによるあなたの真上の答えを見てください。$ scope.formNameからフォームにアクセスできます。彼は実用的な例を提供します
micahblu

3

ng-model="$ctrl.formName"フォームに属性を追加すると、コントローラーでコントローラー内のオブジェクトとしてフォームにアクセスできます。this.formName


0

もちろん、スコープbecのフォームにはアクセスできません。作成されません。htmlテンプレートからのDOMは、コントローラーコンストラクターのように少しずつ読み込まれます。解決策は、DOMが読み込まれ、すべてのスコープが定義されるまで監視することです。

コントローラ内:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.