如何编写一个Angular指令用于' Required If'场景?

时间:2014-09-17 20:02:18

标签: javascript angularjs validation

我正在努力了解如何使用Angular Directives来实现前端验证。虽然我熟悉指令通常的工作方式,但我在任何教程,博客文章甚至实际的Angular文档中都很难找到的是如何有意义地实现有用的验证。 (就此而言,我指的是尚未存在的那个,如this basic tutorial for how to implement a validation attribute

根据我的经验,这些中最常见的是“必需的”方案。如果我的表单中有文本字段A和文本字段B,并且文本字段A有值,则我的业务规则告诉我文本字段B必须具有值。但是,验证指令的各种教程都只依赖于它们所依赖的元素。

问题:我怀疑我正在接近如何实现类似必需的问题如果验证完全错误。在Angular方式中,当且仅当它依赖的字段具有值时,在表单中要求值的正确方法是什么?

2 个答案:

答案 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