【问题标题】:triggering AngularJS ng-model pipeline onBlur触发 AngularJS ng-model 管道 onBlur
【发布时间】:2017-05-13 06:09:54
【问题描述】:

我有这个$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>

【问题讨论】:

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


    【解决方案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 是一个工作示例。

    【讨论】:

    • 写得很好,但是我对新指令有一个问题,当用户复制并粘贴到指令中时,它不会注意到它。有什么想法吗?
    猜你喜欢
    • 2014-10-04
    • 2016-12-09
    • 2013-10-27
    • 2015-03-08
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    相关资源
    最近更新 更多