AngularJs无法访问控制器中的表单对象($ scope)

sar*_*ast 65 angularjs

我正在使用bootstrap-ui更具体的模态窗口.我有一个模态的表单,我想要的是实例化表单验证对象.所以基本上我这样做:

<form name="form">
    <div class="form-group">
        <label for="answer_rows">Answer rows:</label>
        <textarea name="answer_rows" ng-model="question.answer_rows"></textarea>
    </div>
</form>

<pre>
    {{form | json}}
</pre
Run Code Online (Sandbox Code Playgroud)

我可以在html文件中看到form对象而没有任何问题,但是如果我想从控制器访问表单验证对象.它只输出我的空物体.这是控制器示例:

.controller('EditQuestionCtrl', function ($scope, $modalInstance) {
    $scope.question = {};
    $scope.form = {};

    $scope.update = function () {
        console.log($scope.form); //empty object
        console.log($scope.question); // can see form input
    };
});
Run Code Online (Sandbox Code Playgroud)

可能是我无法$scope.form从控制器访问的原因是什么?

Jor*_*rge 74

只是对于那些没有使用的人$scope,而是this在他们的控制器中,你必须在表单名称前面添加控制器别名.例如:

<div ng-controller="ClientsController as clients">
  <form name="clients.something">
  </form>
</div>
Run Code Online (Sandbox Code Playgroud)

然后在控制器上:

app.controller('ClientsController', function() {
  // setting $setPristine()
  this.something.$setPristine();
};
Run Code Online (Sandbox Code Playgroud)

希望它也有助于整体答案.

  • 感谢分享即使问题得到了接受,这也是我需要知道的. (2认同)

mic*_*ael 45

ng-controller是表单元素的父级的正常方法:请删除此行:

$scope.form = {};
Run Code Online (Sandbox Code Playgroud)

如果angular将表单设置为控制器$scope,则用空对象覆盖它.


正如OP所说,这不是这种情况.他正在使用$modal.open,因此控制器不是表单的父级.我不知道一个很好的解决方案.但是这个问题可能被黑了:

<form name="form" ng-init="setFormScope(this)">
...
Run Code Online (Sandbox Code Playgroud)

并在您的控制器中:

$scope.setFormScope= function(scope){
   this.formScope = scope;
}
Run Code Online (Sandbox Code Playgroud)

稍后在您的更新功能中:

$scope.update = function () {
    console.log(this.formScope.form); 

};
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你!我把头发拉出来,直到我意识到你需要使用`form.something`.使用`ng-model`(你需要在一个对象中捕获,而不是一个简单的var)时,这是同样的问题.我以为我理解了范围,但事实证明我还没有... :) (7认同)
  • 我试过这个.然后我得到未定义的值. (4认同)
  • @Michael我发现如果我将表单名称更改为`name ='form.something',那么我会得到价值......任何想法发生了什么?(我会尝试你的建议) (3认同)

LeO*_* Li 21

查看angular ui bootstrap的'modal'的源代码,你会看到该指令有

transclude: true
Run Code Online (Sandbox Code Playgroud)

这意味着模态窗口将创建一个新的子作用域,其父作为控制器$ scope,作为指令作用域的兄弟.然后'form'只能由新创建的子范围访问.

一种解决方案是在控制器范围中定义var

$scope.forms = {};
Run Code Online (Sandbox Code Playgroud)

然后对于表单名称,我们使用类似的东西forms.formName1.这样我们仍然可以通过调用从我们的控制器访问它$scope.forms.formName1.

这是有效的,因为JS中的继承机制是原型链.当子作用域尝试创建时forms.formName1,它首先尝试在自己的作用域中找到表单对象,因为它是在动态创建的,所以它肯定没有它.然后它将尝试从父级(直到原型链)中找到它,并且由于我们在控制器范围中定义它,因此它使用forms我们创建的这个对象来定义变量formName1.因此,我们仍然可以在我们的控制器中使用它来执行以下操作:

if($scope.forms.formName1.$valid){
      //if form is valid
}
Run Code Online (Sandbox Code Playgroud)

有关转换的更多信息,请查看下面Misco的视频,从45分钟开始.(这可能是我所发现的跨越范围的最准确的解释!)

www.youtube.com/watch?v=WqmeI5fZcho


use*_*062 6

不需要ng-init技巧,因为问题是$scope.form在运行控制器代码时没有设置.删除form = {}初始化并使用手表访问表单:

$scope.$watch('form', function(form) {
  ...
});
Run Code Online (Sandbox Code Playgroud)


小智 6

我使用记录的方法.

https://docs.angularjs.org/guide/forms

所以,用户使用表单名称,在"保存"上单击,例如,只需将formName作为参数传递,然后在save方法中提供presto表单(其中formScopeObject根据您在表单中设置的ng-models规范进行更新或者如果您是编辑这将是存储正在编辑的项目的对象,即用户帐户)

<form name="formExample" novalidate>

<!-- some form stuff here -->
Name
<input type="text" name="aField" ng-model="aField" required="" />

<br /><br />

<input type="button" ng-click="Save(formExample,formScopeObject)" />

</form>
Run Code Online (Sandbox Code Playgroud)