1

我有這個$parser這限制了用戶輸入的字符數:觸發AngularJS NG-模型管道的onblur

var maxLength = attrs['limit'] ? parseInt(attrs['limit']) : 11; 

    function fromUser(inputText) { 
     if (inputText) { 
      if (inputText.length > maxLength) { 
       var limitedText = inputText.substr(0, maxLength); 
       ngModel.$setViewValue(limitedText); 
       ngModel.$render(); 
       return limitedText; 
      } 
     } 
     return inputText; 
    } 

    ngModel.$parsers.push(fromUser); 

我想利用這個指令,它有ng-model-options="{updateOn: 'blur'}"輸入元素,但有一個在用戶失去輸入元素的焦點後,整個$parser事件被執行的問題,我希望它在用戶鍵入到輸入字段時執行。

(function (angular) { 
 
    "use strict"; 
 
    angular.module('app', []) 
 
    .controller("MainController", function($scope) { 
 
     $scope.name = "Boom !"; 
 
     $scope.name2 = "asdf"; 
 
    }).directive('limitCharacters', limitCharactersDirective); 
 

 
    function limitCharactersDirective() { 
 
     return { 
 
      restrict: "A", 
 
      require: 'ngModel', 
 
      link: linkFn 
 
     }; 
 

 
     function linkFn(scope, elem, attrs, ngModel) { 
 
      var maxLength = attrs['limit'] ? parseInt(attrs['limit']) : 11; 
 

 
      function fromUser(inputText) { 
 
       if(inputText) { 
 
        if (inputText.length > maxLength) { 
 
         var limitedText = inputText.substr(0, maxLength); 
 
         ngModel.$setViewValue(limitedText); 
 
         ngModel.$render(); 
 
         return limitedText; 
 
        } 
 
       } 
 
       return inputText; 
 
      } 
 

 
      ngModel.$parsers.push(fromUser); 
 
     } 
 
    } 
 

 
})(angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script> 
 

 
<div ng-app="app"> 
 
    without ng-model-options: <input type="text" ng-model="name" limit-characters limit="7" /> 
 
    
 
    <br> 
 
    with ng-model-options <input type="text" ng-model="name2" ng-model-options="{updateOn: 'blur'}" limit-characters limit="7" /> 
 
</div>

回答

1

當用戶輸入在輸入$setViewValue一些值在內部調用。正如angular docs說這是$setViewValue做:

當$ setViewValue被調用時,新的數值將上演 通過$解析器和$驗證管道犯。如果 沒有指定特定的ngModelOptions,則直接通過$ parsers管道發送暫存值 進行處理。在此之後,將調用 $ validators和$ asyncValidators,並將值 應用於$ modelValue。最後,將值設置爲在ng-model屬性中指定的表達式 以及所有已註冊的更改偵聽器,在 中調用$ viewChangeListeners列表。

萬一ngModelOptions指令使用updateOn並沒有列出 默認觸發,所有這些行動將保持等待,直到 觸發的DOM元素的updateOn事件之一。

這意味着$parsers僅用於實際模型更改提交(在您的情況發生在模糊)。

最簡單的解決方案就是不要使用$parsers來限制字符。檢查此question中的其他解決方案。

採用最upvoted答案,你可以修改你的指令,使它看起來像這樣:

function limitCharactersDirective() { 
    return { 
     restrict: "A", 
     require: 'ngModel', 
     link: linkFn 
    }; 

    function linkFn(scope, elem, attrs, ngModel) { 
     var maxLength = attrs['limit'] ? parseInt(attrs['limit']) : 11; 
     angular.element(elem).on("keypress", function(e) { 
      if (this.value.length == maxLength) e.preventDefault(); 
     }); 
    } 
} 

Check this JSFiddle的工作示例。

+0

寫得很好,但我有一個問題與新指令,當用戶複製並粘貼到指令,它不會注意到它。任何想法? – Rachmaninoff