我正在努力了解如何使用Angular Directives来实现前端验证。虽然我熟悉指令通常的工作方式,但我在任何教程,博客文章甚至实际的Angular文档中都很难找到的是如何有意义地实现有用的验证。 (就此而言,我指的是尚未存在的那个,如this basic tutorial for how to implement a validation attribute。
根据我的经验,这些中最常见的是“必需的”方案。如果我的表单中有文本字段A和文本字段B,并且文本字段A有值,则我的业务规则告诉我文本字段B必须具有值。但是,验证指令的各种教程都只依赖于它们所依赖的元素。
问题:我怀疑我正在接近如何实现类似必需的问题如果验证完全错误。在Angular方式中,当且仅当它依赖的字段具有值时,在表单中要求值的正确方法是什么?
答案 0 :(得分:1)
只有在前一个表单元素有效时,才可以尝试使用ng-if添加下一个表单元素。除非第一个元素有效,否则第二个元素将不存在于DOM中。
答案 1 :(得分:1)
我今天做了一些额外的实验。一位同事提示我一个不同的情况,最终导致我为自己解决问题。
我从根本上以错误的方式看问题,对于初学者 - 具体来说,我是以jQuery的方式看待它,期望指令以某种方式揭示读取单个表单元素的方式。这不一定正确,因为我们有一个可以评估的范围。
这是1.3之前的Angular指令代码:
var app = angular.module('app', []);
app.controller('someController', [
'$scope',
function($scope) {
$scope.valueA = '';
$scope.valueB = 'Chicken';
}
]);
app.directive('requiredIf', [
function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attr, model) {
// Read the companion attribute 'otherModelName'
var otherModelName = attr.otherModelName;
scope.$watch(attr.ngModel, function (value) {
var isValid = checkAgainstDependentModel(value);
model.$setValidity('requiredIf', isValid);
});
function checkAgainstDependentModel(value) {
// Assumes that the scope exposes a property with the passed-in
// model name as its name
var field = scope[otherModelName];
var isValid = true;
if(field != null || field != '')
if(value == null || value == '')
isValid = false;
return isValid;
}
}
};
}
]);
...在标记中我们会像这样使用它:
<form name='someForm'>
<input type='text' name='mainField' ng-model='valueA' />
<input type='text' name='subordinateField' ng-model='valueB' required-if other-model-name='valueA' />
<span style='color=red' ng-if='someForm.subordinateField.$error.requiredIf'>
(Required!)
</span>
</form>
此模式可以扩展到1.3之前的各种其他自定义验证。我的研究表明,Angular 1.3将删除 $parsers
和$formatters
,转而支持$validators
和$asyncValidators
。
编辑:我没有使用$formatters/$parsers
,而是更好的想法是在关联的scope.$watch
上执行ngModel
。由于这是一个1.3之前的实现,我们仍然可以model.$setValidity('thing', isValid);
这是基于答案to the question of how best to achieve remote validation pre-1.3。