web-dev-qa-db-ja.com

シンプルなAngularJSフォームはスコープで未定義です

私はjsfiddleでAngularJSフォームをいじり始めていますが、非常に単純なフォームの例が期待どおりに機能しないという問題にすでに遭遇しています。私が持っているのは名前付きフォームであり、何らかの理由でスコープ内に表示されません(FormControllerインスタンスを期待しています)。

fiddle が設定されていますが、基本的なコードは次のとおりです。

HTML

<div id="mainContainer" ng-app="angularTest" ng-controller="MainCtrl">
    <h1>The Form</h1>
    <form name="theForm">
        <input name="myName" type="text" ng-model="model.name" />
        <input name="submit" type="submit" />
    </form>
</div>

JS

var app = angular.module('angularTest', []);

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    console.log($scope.theForm); //displays 'undefined'
}]);

私はjsfiddleでこれの簡単な例をたくさん見つけることができないので、これがそのようなサイトとの奇妙な相互作用であるかどうかはわかりませんでした(私が見つけるほとんどの例は正式なコントローラーを使用していません)。 Plunkerでもチェックを試みましたが、同じ問題が発生します。

私は非常に明白な何かを見逃していると確信していますが、ここで変更または微調整する他の多くのものを見ることができません。どんな助けも大歓迎です!

58
chucknelson

フォームは、コントローラーの$scopeに自身を登録するだけですafterコントローラーが最初に実行された後。したがって、すべてが正しくセットアップされていても、console.log($scope.theForm)は未定義を返します。

theFormの存在に反応する例では、theFormにウォッチャーを設定して、その存在に応じてデバッグテキストを設定できます。

$scope.$watch('theForm', function(theForm) {
    if(theForm) { 
        $scope.formDebugText = 'Form in Scope';
    }
    else {
        $scope.formDebugText = 'Form is Undefined';
    }        
});

http://jsfiddle.net/9k2Jk/1/ で実際に見ることができます

37
Michal Charemza

Watchを使用せずにこれを実行する良い方法(少しやり過ぎです)は、フォームを登録するスコープ内にオブジェクトを定義することです。

HTML

<div id="mainContainer" ng-app="angularTest" ng-controller="MainCtrl">
    <h1>The Form</h1>
    <form name="form.theForm">
        <input name="myName" type="text" ng-model="model.name" />
        <input type="button" value="Here the scope" ng-click="display()"/>
        <input name="submit" type="submit" />
    </form>
</div>

JS

var app = angular.module('angularTest', []);

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    $scope.form = {};
    $scope.display = function () {
        console.log($scope.form.theForm);
    }
}]);
87
IxDay

私にとってそれを修正したのは、$scopeで親オブジェクトを使用することでした。

コントローラー内:

$scope.forms = {};
$scope.registerUser = function registerUser() {
    if ($scope.forms.userForm.$valid) {
        alert('submit');
    }
};

テンプレート内:

<form name="forms.userForm" ng-submit="registerUser()">

理由:

<form name="userForm"...の代わりに<form name="forms.userForm"...を使用すると、フォームが子スコープにアタッチされますが、$ scopeはプロトタイプ継承を使用するため、元の$ scopeで空のオブジェクトリテラルを宣言するとすぐにフォームがアタッチされます代わりに。

30
hofnarwillie

これは、フォーム変数にアクセスするための推奨される方法です。 https://docs.angularjs.org/guide/forms -フォームへのバインドと状態の制御

HTMLの場合:

<form name="form">  
<input type="button" ng-click="reset(form)" value="Reset" />
</form>

Youlはフォームの名前を変数として関数に渡します。

JSの場合:

$scope.reset = function(form) { 
  alert(form); 
};

変数 'form'は現在未定義であってはなりません。

22
bogdanmatra

私の場合、ng-includeを使用してサブスコープを生成したため、現在のスコープ内ではプロパティはundefinedであり、安全でサブスコープの問題を防ぐために、逆の変数を使用してフォームに名前を付ける必要がありますform.theForm

ただし、事前にコントローラーでこのフォーム名を宣言しているであることを確認してください。

<form name="form.theForm">
    <input name="myName" type="text" ng-model="model.name" />
    <input name="submit" type="submit" />
</form>

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    //You have to declare here, else it will trigger undefined error still.
    $scope.form = {
      theForm: {} 
    };

    $scope.reset = function(){
       $scope.form.theForm.$setPristine();
    }
}]);
3
Neeson.Z

このコード行で$ scope.formにアクセスする前に、コントローラーからフォームを再初期化できます。これで、$ scope.formが利用可能になります。

angular.element(jQuery('.form-control')).triggerHandler('input')
1
Ben Warren

この問題に対処するためのディレクティブを作成しました。その属性は、フォームに配置し、フォームの準備ができたときに実行する関数を渡すことができます。

Javascript

angular.module('app').directive('formInit', function(){
  return {
    restrict: 'A',
    scope: {
      init: '&formInit'
    },
    controller: function($scope, $element){
      var name = null;
      if ($element[0] && $element[0].name){
        name = $element[0].name;
      }

      var listener = $scope.$watch('init', function(){
        if ($scope[name] && $scope.init){
          $scope.init();
          listener();
        }
      });
    }
  };
});

HTMLの例

<form name="test" form-init="testing()">

ここで、testingはコントローラースコープの関数です。

0
Simon Trewhella