问题描述
以下code引发错误类型错误:无法读取属性未定义'$质朴'当我点击检查按钮
The following code throws the error "TypeError: Cannot read property '$pristine' of undefined" when I click the "check" button.
app.controller('MainCtrl', function($scope) {
// other stuff
})
.controller('Ctrl2', function($scope) {
$scope.product = {description:'pump'};
$scope.output = 'unknown';
// uncomment to avoid undefined error, still can't see $pristine
// $scope.formHolder = {};
$scope.checkForm = function() {
$scope.descriptionTest = $scope.product.description;
if ($scope.formHolder.productForm.$pristine) {
$scope.output = 'yes';
}
if ($scope.formHolder.productForm.$dirty) {
$scope.output = 'no'
}
}
});
HTML
<body ng-controller="MainCtrl">
<div >
<ng-include ng-controller="Ctrl2" src="'myForm.html'"></ng-include>
</div>
</body>
myForm.html
myForm.html
<form name="productForm" novalidate>
<h2>myForm</h2>
description: <input type="text" name="description" ng-model="product.description"/>
<br>
<button ng-click="checkForm()">Check Form</button>
<br>
Form Pristine: {{output}}
<br><br>
I can see the description: {{descriptionTest}}
</form>
问题是,我的CTRL2无法看到productForm。起初我以为这曾与原型继承做NG-包括做时,它能使孩子的范围,所以我试图在CTRL2加入一个变量:
The problem is that my Ctrl2 can't see the productForm. At first I thought this had to do with the prototypical inheriting that ng-include does when it makes a child scope, so I tried adding a variable in Ctrl2:
$scope.productForm = {};
这摆脱了错误的,但我的遥控器仍没有被正确地看到$质朴或$脏。
This got rid of the error, but my controller still wasn't correctly seeing $pristine or $dirty.
我终于得到它通过添加productForm高于$ scope.formHolder对象工作:
I finally got it working by adding a $scope.formHolder object above the productForm:
.controller('Ctrl2', function($scope) {
$scope.product = {description:'pump'};
$scope.output = 'unknown';
// uncomment to avoid undefined error, still can't see $pristine
$scope.formHolder = {};
$scope.checkForm = function() {
$scope.descriptionTest = $scope.product.description;
if ($scope.formHolder.productForm.$pristine) {
$scope.output = 'yes';
}
if ($scope.formHolder.productForm.$dirty) {
$scope.output = 'no'
}
}
});
HTML
<form name="formHolder.productForm" novalidate>
为什么这项工作?而有没有更好的办法做到这一点?
我弄成这样,因为我有一个工作的形式和放大器;控制器/模板,我想重用别处。我也许应该做一个指令,但除了一切正常的$原始和$形式的肮脏的特点 - 所有的NG-模型瓦尔被正确地传递
I ended up this way because I had a working form & controller / template that I wanted to reuse somewhere else. I should probably make a directive, but everything worked fine except the $pristine and $dirty features of the form--all the ng-model vars were passed correctly.
<一个href=\"http://stackoverflow.com/questions/17474045/how-can-i-set-a-form-contained-inside-a-ng-include-to-be-$p$pstine\">How我可以设置包含在里面的形式NG-包括为prestine?有一个答案是打破所有规则,但显得比较复杂。
How can I set a form contained inside a ng-include to be prestine? has an answer that "breaks all the rules" but seemed more complicated.
在我写的时候没有表单控制器添加$质朴的范围,以及在何种范围?
When I write when does the form Controller add $pristine to the scope, and to what scope?
编辑/答案:
我原来的问题都可以归结为混淆的形式指令如何写入范围。我有IM pression,它将采取的东西。
My original question can be boiled down to confusion about how the form directive writes to the scope. I had the impression that it would take the thing in
<form name="productForm">...
和属性添加到它,就像
$scope.productForm.$pristine = function() {...}
然而,它直接写在productForm的顶部:
however, it writes directly on top of productForm:
$scope.productForm = formObject;
因此,表格对象被存储在儿童和不是父如在选择的回答解释
So, the form object is stored in the Child and not the parent as explained in the selected answer.
在孩子继承范围的关键金块,帮助我的是,链在读征求意见,但不写。所以,如果你设置类似childScope.myThing.property ='123',而它看起来像一个写,它首先要做的读,找出myThing是什么。而设置childScope.myThing ='567'是一个直写,并且不涉及在父链看着所有。这一切更好地解释说:What范围是原型/原型继承的细微差别AngularJS?
The key nugget in child scope inheritance that helped me is that the chain is consulted in reading, but not writing. So if you set something like childScope.myThing.property = '123', while it looks like a write, it first has to do a read to find out what myThing is. Whereas setting childScope.myThing = '567' is a direct write, and doesn't involve looking at the parent chain at all. This is all better explained in: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
推荐答案
要理解为什么用 formHolder
解决方案工作,您必须了解JavaScript原型链第一的。让我们来举例说明而 formHolder
在下面的伪code中的第一种情况:
To understand why the solution with formHolder
work you have to understand JavaScript prototypes chain first. Let's illustrate the first case without formHolder
in the following pseudo code:
$parentScope = {
//I'm a parent scope inside Ctrl2
productForm:{} //to avoid undefined reference error
}
$childScope = {
//I'm a child scope created by by ng-include
__protototype__: $parentScope
}
在该格式
指令被分析它产生这是对 $设置
下的的FormController
范围名表示关键属性
属性值。这是pretty多少等同于:
When the form
directive is parsed it creates FormController
which is set on the $scope
property under key indicated in name
attribute value. This is pretty much equivalent to:
$childScope.productForm = $formCtrl;
在之后的2个范围是这样的:
After which the 2 scopes look like this:
$parentScope = {
//I'm a parent scope inside Ctrl2
productForm:{} //to avoid undefined reference error
}
$childScope = {
//I'm a child scope created by by ng-include
productForm: $formCtrl
__protototype__: $parentScope
}
所以,你实际上结束了在不同范围的 2的属性持不同的对象。
现在,在第二种情况下,你有以下情况:
So you actually ended up with 2 properties on different scopes holding different objects.Now in the second case you have the following situation:
$parentScope = {
//I'm a parent scope inside Ctrl2
formHolder:{} //to avoid undefined reference error
}
$childScope = {
//I'm a child scope created by by ng-include
__protototype__: $parentScope
}
在该格式
指令设置在 $范围
这次它使用不同的属性链的:的FormController
实例
When the form
directive is setting FormController
instance on the $scope
this time it uses different property chain:
$childScope.formHolder.productForm = $formCtrl;
这是等同于文字:
Which is equivalent to writing:
var formHolder = $childScope.formHolder; //since formHolder isn't defined on $childScope
//the JS runtime will look for it in the prototypes chain and find it inside $parentScope
//so here formHolder is the very same object you created and set on $parentScope
formHolder.productForm = $formCtrl;
希望它可以帮助理解为什么第二个选项工作。至于你的第二部分的问题 - 您的解决方案很简单,完全可行的 - 但也有一些其他的方法来处理它,这是最好取决于实际使用环境:
Hope it helps to understand why the second option works. As for the second part of you question - your solution is simple and perfectly viable - but there are couple of other ways to handle it which is best depends on the actual usage context:
- using指令无子范围,提取共同的标记和功能部件
- using指令与沟通会无论是通过直接父作用域属性访问或通过发出的事件状态更改子作用域
- 使用custom包括不会创建子范围指令
- using directive without child scope to extract common markup and parts of functionality
- using directive with child scope that would communicate state changes either via direct parent scope property access or via emitted events
- using a custom include directive that would not create child scope
这篇关于为什么表单中未定义检查$质朴或$使用setDirty()时,NG-包括哪些内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!