以下代码抛出错误" TypeError:无法读取属性' $ pristine'未定义"当我点击"检查"按钮。
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
<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-include在创建子范围时所做的原型继承有关,所以我尝试在Ctrl2中添加变量:
$scope.productForm = {};
这摆脱了错误,但我的控制器仍然没有正确看到$ pristine或$ dirty。
我终于通过在productForm上面添加$ scope.formHolder对象来实现它:
.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>
为什么这样做?还有更好的方法吗?
我这样结束是因为我有一个工作形式&amp;我想在其他地方重用的控制器/模板。我应该做一个指令,但一切都运行正常,除了表格的$ pristine和$ dirty特征 - 所有ng-model vars都正确传递。
How can I set a form contained inside a ng-include to be prestine?有一个答案,&#34;打破了所有规则&#34;但似乎更复杂。
当我写什么时,表单Controller将$ pristine添加到范围,以及范围?
编辑/答案:
我的原始问题可以归结为对form指令如何写入范围的混淆。我的印象是它需要
<form name="productForm">...
并为其添加属性,例如
$scope.productForm.$pristine = function() {...}
然而,它直接在productForm上写道:
$scope.productForm = formObject;
因此,表单对象存储在Child中,而不是父项,如所选答案中所述。
帮助我的子范围继承中的关键金点是链条在阅读时被咨询,但不是写作。因此,如果您设置类似于childScope.myThing.property =&#39; 123&#39;,虽然它看起来像写,但它首先必须执行读取以找出myThing是什么。设置childScope.myThing =&#39; 567&#39;是直接写,并不涉及查看父链。在What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
中可以更好地解释这一点答案 0 :(得分:14)
要了解为什么使用formHolder
工作的解决方案必须首先了解JavaScript prototypes chain。让我们在下面的伪代码中说明没有formHolder
的第一种情况:
$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
}
解析form
指令时,会创建FormController
,该$scope
在name
属性值下指示的键下的$childScope.productForm = $formCtrl;
属性上设置。这几乎相当于:
$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
}
之后,两个范围看起来像这样:
$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
}
所以你实际上最终得到了持有不同对象的 2个不同范围的属性。 现在在第二种情况下,您有以下情况:
form
当FormController
指令在$scope
上设置$childScope.formHolder.productForm = $formCtrl;
实例时,它会使用不同的属性链:
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;
这相当于写作:
{{1}}
希望有助于理解为什么第二个选项有效。至于你提出问题的第二部分 - 你的解决方案很简单且完全可行 - 但还有其他几种方法可以处理它,这最好取决于实际使用情况:
答案 1 :(得分:1)
只需在控制器中定义变量(空对象),并在定义表单时使用它。由于角度JS使用范围原型,当表单将尝试访问内部范围(引导变量)时,它将首先通过范围链并尝试在父范围内找到相同的变量。
<!—- The vars should live in the controller. I placed them here for the example. -—>
<div ng-controller=“controllerName” ng-init="form={}; model={}" >
<div ng-include=“ ‘path-to-the-template’ ”></div>
</div>
<!—- Inside path-to-the-template -—>
<form name="form.createUser">
<input name="name" ng-model="model.name" />
<input name="email" ng-model="model.email" />
</form>
参考链接http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html
答案 2 :(得分:0)
我知道这是一个老问题,但我遇到了类似的问题,我更改了html并将我的ng-controller包含在html文件中。
所以而不是
<ng-include ng-controller="Ctrl2" src="'myForm.html'"></ng-include>
也改变它
<ng-include="'myForm.html'"></ng-include>
然后在myForm.html文件中,将代码包装在div中,并添加ng-controller属性,以便myForm.html成为
<div ng-controller="Ctrl2">
<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>
</div>
现在您的子控制器在ng-include范围内