我正在使用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文件中看到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
};
});
我无法从控制器访问$scope.form
的原因是什么?
答案 0 :(得分:73)
对于那些未在其控制器中使用$scope
而非this
的用户,您必须在表单名称前添加控制器别名。例如:
<div ng-controller="ClientsController as clients">
<form name="clients.something">
</form>
</div>
然后在控制器上:
app.controller('ClientsController', function() {
// setting $setPristine()
this.something.$setPristine();
};
希望它也有助于整套答案。
答案 1 :(得分:45)
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);
};
答案 2 :(得分:21)
查看&#39;模态&#39;的源代码。有角度的ui bootstrap,你会看到指令有
transclude: true
这意味着模态窗口将创建一个新的子范围,其父级在这里是控制器$ scope,作为指令范围的兄弟。那么&#39;形式&#39;只能由新创建的子范围访问。
一种解决方案是在控制器范围中定义var,如
$scope.forms = {};
然后,对于表单名称,我们使用类似forms.formName1
的内容。这样我们仍然可以通过调用$scope.forms.formName1
来从控制器访问它。
这是有效的,因为JS中的继承机制是原型链。当子作用域尝试创建forms.formName1
时,它首先尝试在自己的作用域中找到表单对象,因为它是动态创建的,所以它绝对没有。然后它将尝试从父级(直到原型链)中找到它,并且由于我们在控制器范围中定义了它,因此它使用了这个&#39; forms
&#39;我们创建的对象来定义变量formName1
。因此,我们仍然可以在我们的控制器中使用它来执行以下操作:
if($scope.forms.formName1.$valid){
//if form is valid
}
有关转换的更多信息,请查看以下Misco的视频,时间为45分钟。 (这可能是我曾经发现过的跨越范围的最准确的解释!!!)
www.youtube.com/watch?v=WqmeI5fZcho
答案 3 :(得分:6)
不需要ng-init技巧,因为问题是在运行控制器代码时未设置$scope.form
。删除form = {}
初始化并使用监视访问表单:
$scope.$watch('form', function(form) {
...
});
答案 4 :(得分: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>
答案 5 :(得分:0)
要扩展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
}
});
答案 6 :(得分:0)
对于那些使用Angular 1.5的人,我的解决方案是在$ postlink阶段观看表单:
$postLink() {
this.$scope.$watch(() => this.$scope.form.$valid, () => {
});
}