范围内未定义简单的 AngularJS 表单

Posted

技术标签:

【中文标题】范围内未定义简单的 AngularJS 表单【英文标题】:Simple AngularJS Form is undefined in Scope 【发布时间】:2014-04-21 14:29:23 【问题描述】:

我开始在 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 上检查,但我遇到了同样的问题。

我确定我遗漏了一些非常明显的东西,但我看不出这里有很多其他需要改变或调整的东西。非常感谢任何帮助!

【问题讨论】:

当我的表单嵌套在一个带有 ng-if 的元素中时,我遇到了这个问题。改用 ng-show 解决了这个问题。 【参考方案1】:

在我的例子中,我使用ng-include 来生成一个子作用域,所以在当前作用域内属性是undefined,为了安全和防止子作用域问题,我们应该使用反向变量来命名表单,就像@ 987654323@.

但请确保您已提前在控制器中声明了此表单名称

<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();
    
]);

【讨论】:

【参考方案2】:

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

【讨论】:

这可能不是解决此问题的最佳方法,但通常是将表单验证带入控制器的好方法。感谢分享。 注意尝试直接绑定到form 是行不通的,它必须是form.someNewName【参考方案3】:

在尝试使用这行代码访问 $scope.form 之前,您可以从控制器重新初始化表单。然后 $scope.form 将可用。

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

【讨论】:

【参考方案4】:

为我解决的问题是在 $scope 上使用父对象。

在控制器中:

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

在模板中:

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

原因:

如果您使用&lt;form name="userForm"... 而不是&lt;form name="forms.userForm"...,它会将表单附加到子范围,但是因为 $scopes 使用原型继承,所以只要我在原始 $scope 上声明了一个空对象文字,表单就会附加到取而代之。

【讨论】:

所以我将ng-controller="MainCtrl" 添加到form 中,这似乎让它直接绑定到该范围。这种方法有什么问题吗?【参考方案5】:

这是访问表单变量的推荐方法: https://docs.angularjs.org/guide/forms - 绑定到表单和控制状态

html 中:

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

您将表单的名称作为变量传递给函数。

在 JS 中:

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

现在不应未定义变量“form”。

【讨论】:

你将如何测试这个?【参考方案6】:

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

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

【讨论】:

【参考方案7】:

表单仅在控制器初始运行之后向控制器的$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/看到实际操作

【讨论】:

啊,我早该知道的。我已经处理过这些类型的异步加载行为!谢谢!这一切最终都会沉没;) 如果您只需要在表单报告它存在 var formWatchUnbind = $scope.$watch 然后 if(theForm)formWatchUnbind(); //在这里做你想做的 这对我不起作用。 $scope.theForm 始终未定义 @michal :感谢您的回答。仅当控制器完成初始运行时,任何显示“表单”的文档才会注册到控制器范围。会有帮助的。谢谢

以上是关于范围内未定义简单的 AngularJS 表单的主要内容,如果未能解决你的问题,请参考以下文章

Typescript + Require.js + PIXI 6 - 导入附加到窗口但在主范围内未定义

错误:此范围内未声明“NULL”

NgRX实体:ID在州内未定义

AngularJS模态对话框表单对象在控制器中未定义

绑定文本框时,AngularJs范围未定义

指令的angularjs typescript控制器类中未定义的范围变量