触发 AngularJS ng-model 管道 onBlur
triggering AngularJS ng-model pipeline onBlur
我有这个 $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
所做的:
When $setViewValue is called, the new value will be staged for
committing through the $parsers and $validators pipelines. If there
are no special ngModelOptions specified then the staged value is sent
directly for processing through the $parsers pipeline. After this, the
$validators and $asyncValidators are called and the value is applied
to $modelValue. Finally, the value is set to the expression specified
in the ng-model attribute and all the registered change listeners, in
the $viewChangeListeners list are called.
In case the ngModelOptions directive is used with updateOn and the
default trigger is not listed, all those actions will remain pending
until one of the updateOn events is triggered on the DOM element.
这意味着 $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 一个工作示例。
我有这个 $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
所做的:
When $setViewValue is called, the new value will be staged for committing through the $parsers and $validators pipelines. If there are no special ngModelOptions specified then the staged value is sent directly for processing through the $parsers pipeline. After this, the $validators and $asyncValidators are called and the value is applied to $modelValue. Finally, the value is set to the expression specified in the ng-model attribute and all the registered change listeners, in the $viewChangeListeners list are called.
In case the ngModelOptions directive is used with updateOn and the default trigger is not listed, all those actions will remain pending until one of the updateOn events is triggered on the DOM element.
这意味着 $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 一个工作示例。