通过摘要运行验证指令

Run validation directive via digest

本文关键字:验证 指令 运行      更新时间:2023-09-26

此指令用于确定给定值是否在与其关联的数据列表中。当我输入输入时,它可以完美运行,但如果数据列表由于周期(向其添加值)而更改$digest则它将无法工作。如果我随后更新输入,它将正常运行

app.directive('list', function (){
    return {
        restrict: "A",
        require: "ngModel",
        priority: 100,
        link: function(scope, elem, attr, ngModel){
            var list;
            //For DOM -> model validation
            ngModel.$validators.list = function(value){
                if(!list){
                    var options = document.getElementById(attr.list).options;
                    var list = [];
                    for(var i=options.length-1; i>=0; i--){
                        if(isString(options[i].getAttribute("valid"))){
                            if(options[i].label){list.push(options[i].label.toLowerCase())}
                            if(options[i].value){list.push(options[i].value.toLowerCase())}
                        }
                    };
                }
                var valid = (value||!value==""?list.indexOf(value.toLowerCase()) !== -1:true);
                return (!list.length)||valid;
            };
        }
    };
});
您需要

监视列表,然后触发ngModel.$validate();然后运行验证管道...

app.directive('list', function (){
    return {
        restrict: "A",
        require: "ngModel",
        priority: 100,
        link: function(scope, elem, attr, ngModel){
            var list;

        scope.$watch(function () {
            return $parse(attrs.list)(scope);
        }, function () {
            ngModel.$validate();
        });

            //For DOM -> model validation
            ngModel.$validators.list = function(value){
                if(!list){
                    var options = document.getElementById(attr.list).options;
                    var list = [];
                    for(var i=options.length-1; i>=0; i--){
                        if(isString(options[i].getAttribute("valid"))){
                            if(options[i].label){list.push(options[i].label.toLowerCase())}
                            if(options[i].value){list.push(options[i].value.toLowerCase())}
                        }
                    };
                }
                var valid = (value||!value==""?list.indexOf(value.toLowerCase()) !== -1:true);
                return (!list.length)||valid;
            };
        }
    };
});

你真的需要阅读这个关于如何"在角度中思考"的SO问题。

在某处,您有一个<datalist>,您通过 list 属性将其 id 传递给您的指令。我想这很接近你所拥有的:

<datalist id="myDatalist">
  <options ng-repeat="item in items" value="{{item.value}}">{{item.label}}</options>
</datalist>
<input ng-model="foo" list="myDatalist">

不要尝试从<options>元素或 DOM 中的其他任何位置"提取"值。您已经有$scope.items(或您如何命名) - 使用它将其传递给您的list指令:

.directive("list", function(){
  return {
    // other directive properties,
    scope: {
       list: "="
    },
    require: "ngModel",
    link: function(scope, element, attrs, ngModel){
       scope.$watchCollection("list", function(){
          ngModel.$validate();
          // do whatever else you need in response to a change in list
       });
       // register validators, etc...
    }
  }
});

然后指令的用法如下:

<input ng-model="foo" list="items">

这不仅会使用 Angular 来监视底层数据的变化,还会将您的逻辑与 DOM 分离,因此如果您决定稍后更改 ID,或者使用不带 <option> s 的不同元素,那么您的指令不会更改。