2013-12-10 71 views
7

我在我的應用程序中有一個自定義驗證指令(代碼如下)。 問題是,當需要一個或多個表單域並且chrome自動填充它們時,這些域將保持無效,直到用戶手動更改爲止。 我懷疑發生這種情況的原因是,在角度甚至是自舉之前,chrome會填充字段。

有沒有辦法解決這個問題?

代碼:

app.directive('myValidate', function($timeout, $filter) { 
    return { 
     require: 'ngModel', 
     link: function(scope, elm, attrs, ctrl) { 
       var validator = function(viewValue){ 
       var viewValueStr = viewValue + ''; 
       scope.valid = true; 
       scope.fieldName = attrs.name; 
       var nameStr = attrs.name + ''; 
       if(!attrs.displayName || attrs.displayName.length == 0){ 
        // var nameObj = nameStr.split('_'); 
        // for(var i = 0; i < nameObj.length; ++i){ 
        // nameObj[i] = nameObj[i].substr(0, 1).toUpperCase() + nameObj[i].slice(1); 
        // } 
        // var nameStrParsed = nameObj.join(' ');//olde code, working on name, not Hebrew comaptible 
        var nameStrParsed = attrs.placeholder + ''; 
       } 
       else{//data-display-name attribute, the error display is different than the placeholder value 
        var nameStrParsed = attrs.displayName; 
       } 

       scope.fieldErrorDisplay = Boolean(nameStrParsed) ? nameStrParsed : $filter('translate')('THISFIELD'); 
       var valueRequired = scope.$eval(attrs.valueRequired); 
       if(valueRequired && viewValueStr.length == 0 && !attrs.minLength){ 
        scope.valid = false; 
        scope.requirementSpec[nameStr] = [{ 
         'msg' : scope.fieldErrorDisplay + ' ' + $filter('translate')('ISREQUIRED'), 
         'class' : undefined 
        }]; 
        } 
        else{ 
         // scope.fieldErrorDisplayObj[nameStr] = scope.fieldErrorDisplay + ' must meet the following requirements: '; 
         scope.requirementSpec[nameStr] = []; 
         if(attrs.minLength){ 
          var itemValidity = viewValue.length >= attrs.minLength; 
          scope.valid = !itemValidity ? false : scope.valid; 
          var item = { 
          'msg' : $filter('translate')('MINLENGTH', {PARAM: attrs.minLength + ''}), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 
         } 
         else if(attrs.valueRequired){ 
          var itemValidity = viewValue && viewValueStr && viewValueStr.length >= 1; 
          scope.valid = !itemValidity ? false : scope.valid; 
          var item = { 
          'msg' : $filter('translate')('FIELDREQUIRED'), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 
         } 
         if(attrs.maxLength){ 
          var itemValidity = viewValue.length <= attrs.maxLength; 
          scope.valid = !itemValidity ? false : scope.valid; 
          var item = { 
          'msg' : $filter('translate')('MAXLENGTH', {PARAM: attrs.maxLength + ''}), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 
         } 
         if(attrs.minLetters){ 
          var itemValidity = (viewValue && /[A-z]/.test(viewValue)); 
          scope.valid = !itemValidity ? false : scope.valid; 
          var item = { 
          'msg' : $filter('translate')('MINLETTERS', {PARAM: attrs.minLetters + ''}), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 
         } 
         if(attrs.minNumbers){ 
          var itemValidity = (viewValue && /\d/.test(viewValue)); 
          scope.valid = !itemValidity ? false : scope.valid; 
          var item = { 
          'msg' : $filter('translate')('MINNUMBERS', {PARAM: attrs.minNumbers + ''}), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 
         } 
         if(attrs.validUrl){ 
          // if(viewValue.indexOf('http') == -1){ 
          // viewValue = 'http://' + viewValue; 
          // ctrl.$setViewValue(viewValue); 
          // } 
          // else if(viewValue.indexOf('http') != 0){ 
          // var httpIndex = viewValue.indexOf('http');w 
          // viewValue = viewValue.substr(httpIndex); 
          // ctrl.$setViewValue(viewValue); 
          // } 
          // var urlPattern = new RegExp("(http|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:/~+#-]*[\[email protected]?^=%&amp;/~+#-])?"); 
          var urlPattern = new RegExp(/^(https?):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i); 
          //(http|https):\/\/([a-zA-Z0-9]+\.)?[a-zA-Z0-9][a-zA-Z0-9-]+\.[a-zA-Z]{2,6}?(.+){0, 100}$/i) 
          var itemValidity = !viewValue || viewValue.length == 0 || urlPattern.test(viewValue); 
          scope.valid = !itemValidity ? false : scope.valid; 
          // console.log(itemValidity); 
          var item = { 
          'msg' : $filter('translate')('VALIDURL'), 
          'class' : itemValidity ? 'valid' : undefined 
          }; 
          scope.requirementSpec[nameStr].push(item); 

         } 
        } 

        if(scope.valid) { 
         ctrl.$setValidity(nameStr, true); 
         elm.removeClass('ng-required-invalid').removeClass('validatorError').removeClass('ng-invalid').addClass('ng-valid'); 
         return viewValue; 
        } 
        else { 
         ctrl.$setValidity(nameStr, false);      
         return undefined; 
        } 
       } 
       if(!scope.requirementSpec){ 
       scope.requirementSpec = {}; 
       } 
       if(Boolean(attrs.valueRequired) || Boolean(attrs.minLength)){ 
        ctrl.$setValidity(attrs.name, false); 
        // elm.removeClass('ng-valid').addClass('ng-invalid'); 
       } 

      ctrl.$parsers.unshift(function(viewValue) { 
       return validator(viewValue); 
      }); 
      ctrl.$formatters.unshift(function(viewValue) { 
       if(viewValue && viewValue != "" && viewValue.length > 0) 
       return validator(viewValue); 
      }); 
     } 
    }; 
}) 

回答

2

下面的代碼添加到我的自定義驗證指令的底部:

scope.$on('triggerValidator', function(e, val){ 
     var viewValue = typeof $ === 'function' ? $('[name="' + attrs.name + '"]').val() : document.getElementsByName(attrs.name)[0].value; 
     if(viewValue && viewValue.length > 0){ 
     try{ 
      ctrl.$setViewValue(viewValue); 
      validator(viewValue); 
     } 
     catch(SUPPRESS){} 
     } 
    }); 

而下面我控制器底部:

$timeout(function(){ 
     $rootScope.$broadcast('triggerValidator'); 
    }, 500) 

請注意,使用jQuery時,超時200ms就足夠了,當使用原生JS選擇器時,我必須將超時時間增加到500ms。

try-catch塊在那裏可以捕獲當嘗試設置包含字符'@'的視圖值時Angular會引發的奇怪分析器異常,但可以正常工作!

這也是很好的跟蹤官問題的角度庫: https://github.com/angular/angular.js/issues/1460

1

我懷疑這種情況歸因於鉻前角甚至白手起家

如果田野裏角白手起家之前設置填充字段的事實 - - 它應該可以正常工作。我認爲問題的另一方面:Chorme在Angular啓動後設置了字段,但沒有通知Angular關於狀態變化。

有一對夫婦的可以工作的方法,但是沒有人會認爲是很優雅:

  1. 手動引導 - 只是給一些150-350ms延遲。
  2. 要保存本地存儲中的值並手動設置它們。 Here是支持它的不錯的模塊。
  3. 要使用$ timeout在100-200ms的間隔中大約2-10次來明確強制$digest

我可能會去選項3.,因爲它是最容易實現,可能是最可靠的。

+0

謝謝您的答覆,我會檢查這一點,並讓你知道,如果你的解決方案的工作! –

+0

沒有很好的工作:( 只好使用CSS選擇器 –

相關問題