我有这个$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>
最佳答案
当用户在输入$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作为工作示例。