触发AngularJS ng-model管道onBlur

时间:2017-05-13 06:09:55

标签: javascript angularjs validation directive angularjs-ng-model

我有$parser这限制了用户输入的字符数:

  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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

当用户输入输入$setViewValue中的某个值时,会在内部调用。正如angular docs中所述,这是$setViewValue所做的:

  

当调用$ setViewValue时,将为其暂存新值   通过$ parsers和$ validators管道提交。如果有   没有指定特殊的ngModelOptions,然后发送暂存值   直接通过$ parsers管道进行处理。在此之后,   调用$ validators和$ asyncValidators并应用该值   到$ modelValue。最后,将值设置为指定的表达式   在ng-model属性和所有已注册的更改侦听器中   调用$ viewChangeListeners列表。

     

如果ngModelOptions指令与updateOn和。一起使用   未列出默认触发器,所有这些操作都将保持挂起状态   直到在DOM元素上触发updateOn事件之一。

这意味着$parsers仅用于实际的模型更改提交(在您的情况下会发生模糊)。

解决您问题的最简单方法是不使用$parsers来限制字符。请查看此question中的其他解决方案。

使用最受欢迎的答案,您可以修改您的指令,使其如下所示:

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是一个有效的例子。