我试图弄清楚如何在不使用表单标签的情况下检查ngModel的状态。我没有包装器只是带有ngModel的基本输入元素。
到目前为止我找到的所有例子都是用于表格验证,在这种情况下,没有表格。
当我尝试类似的事情时:
HTML
<input type="text" ng-model="lastname">
SCRIPT:
if($scope.lastname.$dirty) {
console.log('last name has changed');
}
我未定义。
有没有办法检查ngModel的状态而不向它添加watch指令?它似乎是基本的东西,是框架的一部分。为什么这不起作用?
答案 0 :(得分:22)
有两种方法:
ng-form
:<span ng-form="myForm">
<input type="text" name="name" ng-model="name" required/>
</span>
现在,您可以在控制器中的$scope.myForm.name
或视图中使用myForm.name
访问模型:
var isPristine = $scope.myForm.name.$pristine;
angular.element().controller('ngModel')
(不要做这个,坏坏坏)或者,你可以破解它。但这将是丑陋的,不可测试的,粗暴的:
var elem = angular.element(document.getElementById('myElement'));
var model = elem.controller('ngModel');
var isPristine = model.$pristine;
我的例子和你的唯一区别是输入字段在ng-repeater中。认为这无关紧要,但我猜它确实如此。
现在是时候问自己你在做什么以及为什么......你仍然可以使用ng-form
获得所需的信息,但你需要做一些疯狂的事情我不会不推荐:
<div ng-repeater="item in items track by $index">
<span ng-form="rptrForm">
<input type="text" name="name" ng-model="item.name" required/>
</span>
</div>
..开始疯狂:
// get the first child scope (from the repeater)
var child = $scope.$$childHead;
while(child) {
var isPristine = child.rptrForm.$pristine;
var item = child.item;
if(!isPristine) {
// do something with item
}
child = child.$$nextSibling;
}
我不确定你的最终目标是什么,但你可能想重新考虑一下你的目标和原因。为什么需要在控制器中以编程方式访问$ pristine?有什么替代品?等
我,其中一个,会尝试利用ng-change
事件并在我的转发器中更新我的项目上的一些标志,并留下ng-form的内容进行验证:
<div ng-repeat="item in items track by $index" ng-form="rptrForm">
<input type="text" name="name" ng-model="item.name" ng-change="item.nameChanged = true" required/>
<span ng-show="rptrForm.name.$error.required>Required</span>
</div>
答案 1 :(得分:5)
如果您为
<form>
元素提供name
属性,那么<form>
将是 作为属性添加到$scope
对象 然后,字段控制器将附加到form
属性。
看起来很奇怪,你必须定义一个带有form
属性的封闭式name
,如下所示:
<form name="myForm">
<input type="text" name="lastName" ng-model="lastname">
</form>
并使用以下命令调用该属性:
$scope.myForm.lastname.$dirty
确实,ngModelController
(字段)附加到ngFormController
(表单)。
答案 2 :(得分:0)
我使用Ben Lesh的答案来处理同样的问题。我正在显示一个通知首选项列表,我的目标是使用已更改的模型来查看我的api。不仅仅是ng-changed;价值改变了。
我首先在控制器上初始化一些私有状态:
// Private state
var originalModels = {};
var changedModels = [];
然后我存储从API检索的原始模型的副本:
// Create a hash of copies of our incoming data, keyed by the unique Code
for (var i = 0; i <= data.length - 1; i++) {
var np = data[i];
originalModels[np.Code] = angular.copy(np);
}
接下来,我们要确保在模型更改时,将其添加到已更改的模型集合中(如果未发生实际更改,则将其从集合中删除):
function modelChanged(m) {
var originalModel = originalModels[m.Code];
var hasChanged = !angular.equals(originalModel, m);
// If the model has changed and is not present in our collection of changed models, add it
if (hasChanged && changedModels.indexOf(m) === -1) {
changedModels.push(m);
}
// If the model has not changed and is present in our collection of changed models, remove it
if (!hasChanged && changedModels.indexOf(m) > -1) {
var i = changedModels.indexOf(m);
changedModels.splice(i, 1);
}
}
最后,我们在ng-repeat中将这些联系在一起:
<tr ng-repeat="np in npc.notificationPreferences">
<td>{{np.DisplayName}}</td>
<td>
<input type="checkbox"
ng-model="np.Sms"
ng-checked="np.Sms"
ng-disabled="!np.SmsEnabled"
ng-change="npc.modelChanged(np)"/>
</td>
</tr>
现在,我只是推送已更改的模型,而不是将每一行推回到我的API。如果没有任何实际更改(即changedModels集合为空),这还有一个附带好处,即能够禁用提交按钮。