简单的AngularJS表单在Scope中未定义

时间:2014-03-16 11:53:41

标签: forms 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检查,但我遇到了同样的问题。

我确定我错过了一些非常明显的东西,但是我无法在这里看到许多其他要改变或调整的东西。非常感谢任何帮助!

6 个答案:

答案 0 :(得分:86)

在不使用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);
    }
}]);

答案 1 :(得分:37)

在控制器最初运行之后,表单仅向控制器$scope注册。因此,即使一切设置正确,console.log($scope.theForm)也将返回undefined。

在您的示例中,对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/

中看到

答案 2 :(得分:30)

为我修复的是在$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"...,它会将表单附加到子作用域,但因为$ scopes使用原型继承,所以只要在原始$ scope上声明了一个空对象文字,表格附在它上面。

答案 3 :(得分:22)

这是访问表单变量的推荐方法: 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); 
};

现在不应该定义变量'形式'。

答案 4 :(得分:3)

在我的情况下,我使用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();
    }
}]);

答案 5 :(得分:0)

我写了一个指令来处理这个问题。它是一个属性,您可以将其放在表单上并传递一个函数,该函数将在表单准备就绪时执行。

<强>的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是控制器范围的函数。