AngularJS中表单设置有效性的延迟

Posted

技术标签:

【中文标题】AngularJS中表单设置有效性的延迟【英文标题】:Delay on Form setvalidity in AngularJS 【发布时间】:2016-09-22 11:51:36 【问题描述】:

我正在使用设置表单有效性的指令。一切都会相应地工作,但是自定义有效性的布尔值不会立即返回,确切地说,它需要进行额外的按键操作。顺便说一句,我使用“element.blur”来设置自定义有效性。

这是 html 代码:

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
      <form ng-controller="myCtrl" name="bioManagementForm" novalidate>
        <fieldset ng-repeat="bioEducation in bioEducations" data-ng-form="nestedbioEducationsForm">
          Degree: <br />
          Availability: --  nestedbioEducationsForm.bio_education_degree.$error.available 
          <input class="form-control input-form" ng-model="bioEducation.bio_education_degree" name="bio_education_degree" id="bio_education_degree" auto-complete-validation ui-items="searchDegreeItems">
          <span class="errors" id="error-bio-education-degree">
                        <span ng-if="nestedbioEducationsForm.bio_education_degree.$error.available"> * Not Available <br /></span>
                    </span>
                    School: <br />
                    Availability: --  nestedbioEducationsForm.bio_education_school.$error.available 
                    <input class="form-control input-form" type="text" ng-model="bioEducation.bio_education_school" name="bio_education_school" id="bio_education_school" auto-complete-validation ui-items="searchSchoolItems">
          <span class="errors" id="error-bio-education-school">
                        <span ng-if="nestedbioEducationsForm.bio_education_school.$error.available"> * Not Available <br /></span>
                    </span>
        </fieldset>
    </form>
  </body>
</html>

这里是JS代码:

// Code goes here

var myApp = angular.module('myApp', []); 


myApp.controller('myCtrl', function($scope)
  $scope.name = "dean";
  $scope.originalBioEducations = [];
    $scope.bioEducations = angular.copy($scope.originalBioEducations);
    $scope.searchSchoolItems = ["Don Bosco", "JRU", "UST", "FEU"];
    $scope.searchDegreeItems = ["BSIT", "BSED", "ECE", "COE"];
);

function monkeyPatchAutocomplete() 
    // Don't really need to save the old fn, 
    // but I could chain if I wanted to
    var oldFn = $.ui.autocomplete.prototype._renderItem;

    $.ui.autocomplete.prototype._renderItem = function( ul, item) 
        var re = new RegExp( "(" + this.term + ")", "gi" );
        var t = item.label.replace(re,"<span style='font-weight:bold;color:#04508e;'>" + this.term + "</span>");
        return $( "<li></li>" )
        .data( "item.autocomplete", item )
        .append( "<a>" + t + "</a>" )
        .appendTo( ul );
    ;
 
monkeyPatchAutocomplete();
function remove_duplicates_safe(arr) 
        var obj = ;
        var arr2 = [];
        for (var i = 0; i < arr.length; i++) 
            if (!(arr[i] in obj)) 
                arr2.push(arr[i]);
                obj[arr[i]] = true;
            
        
        return arr2;
     

myApp.directive('autoCompleteValidation', function($timeout)
        return 
            require: 'ngModel',
            scope: 
                uiItems: "="
            ,
            link: function(scope, element, attrs, ctrl)
                scope.$watchCollection('uiItems', function(val)
                    items = scope.uiItems.filter(function(n) return n != undefined );
                    element.autocomplete(
                        source: remove_duplicates_safe(items),
                        minLength:2,
                    );
                    element.bind('blur', function()
                        _val = element.val();
                        _index = items.indexOf(_val);
                        if(_index == -1)
                            ctrl.$setValidity('available', false);
                            console.log("dean");
                        else
                            ctrl.$setValidity('available', true);
                            console.log("armada");
                        
                    );
                );
            
        
    );

附言

该应用是通过 ng-repeat 实现的动态字段。我也在使用 data-ng-form 进行动态验证。两个输入字段都由 jquery ui 自动完成运行。验证应该检测字段上的值是否在数组内的自动完成选项中(具有“项目”范围变量的选项)。如果输入字段上的选项不在选项中,它应该会抛出错误。

这是 plunkr 中的一个示例:http://plnkr.co/edit/2EPuhRiR9OncV8z7q018?p=preview

【问题讨论】:

【参考方案1】:

如果您想避免添加按键事件,您应该在ngModelController 上使用 $validators 对象属性。无论如何,这是创建验证器指令的正确方法。您可能还想将更改事件添加到您的自动完成中,以便您可以 $setViewValue。

               scope.$watchCollection('uiItems', function(val)
                items = scope.uiItems.filter(function(n) return n != undefined );
                element.autocomplete(
                    source: remove_duplicates_safe(items),
                    minLength:2,
                    change: function () 
                      ctrl.$setViewValue(element.val());
                    
                );
            );
            
            ctrl.$validators.available = function (modelValue, viewValue) 
              var value = modelValue || viewValue;
              if (items) 
              var _index = items.indexOf(value);
              
              return _index !== -1;
              
            

plunker:http://plnkr.co/edit/pcARNdakhEouqnCIQ2Yt?p=preview

顺便说一句。不要动态创建全局变量,在名称开头添加 _ 不会使它们成为本地或私有的。

【讨论】:

以上是关于AngularJS中表单设置有效性的延迟的主要内容,如果未能解决你的问题,请参考以下文章

isValid 表单验证然后运行一个函数 AngularJS

Angularjs 字段仅有效其值大于零

AngularJS API

单击angularjs中的提交表单时如何删除“请填写此字段”弹出但其他验证应该有效

如何将数据作为表单数据而不是请求有效负载发布?

AngularJs 在 Modal 中清除表单并将其设置为 ng-invalid