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



我正在使用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

我可以毫无问题地在 html 文件中看到表单对象,但是如果我想从控制器访问表单验证对象。它只是输出我空的对象。下面是控制器示例:

.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
};
});

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

仅适用于不使用$scope而是this的人,在他们的控制器中,您必须在表单名称之前添加控制器别名。例如:

<div ng-controller="ClientsController as clients">
<form name="clients.something">
</form>
</div>

然后在控制器上:

app.controller('ClientsController', function() {
// setting $setPristine()
this.something.$setPristine();
};

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

如果ng-controller是表单元素的父元素,则正常方式: 请删除此行:

$scope.form = {};

如果 angular 将窗体设置为控制器$scope则用空对象覆盖它。


正如OP所说,这里的情况并非如此。他使用的是$modal.open,所以控制器不是表单的父级。我不知道一个好的解决方案。但是这个问题可以被黑客入侵:

<form name="form" ng-init="setFormScope(this)">
...

在控制器中:

$scope.setFormScope= function(scope){
this.formScope = scope;
}

稍后在您的更新函数中:

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

查看 angular ui 引导程序的"模态"的源代码,你会看到指令有

transclude: true

这意味着模式窗口将创建一个新的子作用域,其父作用域是控制器$scope,作为指令作用域的同级。然后,"表单"只能由新创建的子范围访问。

一种解决方案是在控制器作用域中定义一个 var,例如

$scope.forms = {};

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

这是有效的,因为JS中的继承机制是原型链。当子作用域尝试创建forms.formName1时,它首先尝试在自己的作用域中查找表单对象,而该作用域绝对没有它,因为它是动态创建的。然后它将尝试从父级(直到原型链)中找到它,在这里,由于我们在控制器范围内定义了它,它使用我们创建的这个'forms'对象来定义变量formName1。因此,我们仍然可以在控制器中使用它来做我们的事情,例如:

if($scope.forms.formName1.$valid){
//if form is valid
}

更多关于隐蔽的信息,请看下面Misco的45分钟视频(这可能是我发现的最准确的解释!!)

www.youtube.com/watch?v=WqmeI5fZcho

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

$scope.$watch('form', function(form) {
...
});

我使用记录的方法。

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

因此,用户表单名称,在"保存"上单击例如只需将formName作为参数传递,嘿presto表单在保存方法中可用(其中formScopeObject根据您在表单中设置的ng模型规范进行优化,或者如果您正在编辑,这将是存储正在编辑的项目的对象,即用户帐户)

<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>

要扩展 user1338062 的答案: 我多次使用的解决方案来初始化控制器中的某些内容,但必须等到它实际可以使用:

var myVarWatch = $scope.$watch("myVar", function(){
if(myVar){
//do whatever init you need to
myVarWatch();    //make sure you call this to remove the watch
}
});

对于那些使用 Angular 1.5 的用户,我的解决方案是在$postlink舞台上$watching表单:

$postLink() {
this.$scope.$watch(() => this.$scope.form.$valid, () => {
});
}

最新更新