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