当我单击“检查”按钮时,以下代码会引发错误“TypeError: Cannot read property '$pristine' of undefined”。
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>
为什么这行得通?有没有更好的方法来做到这一点?
我以这种方式结束了,因为我有一个工作表单和控制器/模板,我想在其他地方重用。我可能应该做一个指令,但是除了表单的 $pristine 和 $dirty 特性之外,一切都很好——所有的 ng-model 变量都被正确传递了。
如何将包含在 ng-include 中的表单设置为 prestine?有一个“违反所有规则”的答案,但似乎更复杂。
当我写时,表单控制器何时将 $pristine 添加到范围,以及添加到什么范围?
编辑/回答:
我最初的问题可以归结为对表单指令如何写入范围的混淆。我的印象是它会把东西放进去
<form name="productForm">...
并为其添加属性,例如
$scope.productForm.$pristine = function() {...}
但是,它直接写在 productForm 之上:
$scope.productForm = formObject;
因此,表单对象存储在子项中,而不是所选答案中解释的父项。
对我有帮助的子范围继承中的关键金块是在阅读时咨询了链条,而不是写作。因此,如果您设置了 childScope.myThing.property = '123' 之类的内容,虽然它看起来像写入,但它首先必须进行读取以找出 myThing 是什么。而设置 childScope.myThing = '567' 是直接写入,根本不涉及查看父链。这在下面得到了更好的解释:AngularJS 中范围原型/原型继承的细微差别是什么?