我在输入上使用debounce:
<input type="text"
ng-model="model.qty"
ng-model-options="{ debounce : 1000 }"
min="{{model.min}}" max="{{model.max}}" step="1"
qty-input validate-model-setting>
我有一个指令来处理禁用此输入的增量按钮和减量按钮:
app.directive('qtyInput', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
scope.$watch(attrs.ngModel, function(n, o) {
var val = parseInt(n);
if(!isNaN(val)) {
if(val + 1 > model.max) {
scope.quantityIncDisabled = true;
} else {
scope.quantityIncDisabled = false;
}
if(val - 1 < model.min) {
scope.quantityDecDisabled = true;
} else {
scope.quantityDecDisabled = false;
}
}
});
}
}
});
问题是,该指令上的手表正在查看模型。我需要它来查看$viewValue
。这是因为,由于去抖动,在输入中输入和使用递增/递减按钮之间存在竞争条件。例如,您可以在输入达到1(最小值)后反复单击减量按钮1秒钟,然后在去抖动结束后,减量按钮将被禁用。相反,我希望在输入达到1时立即禁用该按钮,而不是在等待完全去抖秒之后。我最好的猜测是,这意味着在$watch
上加$viewValue
,但我不知道如何在指令中找到它。
作为参考,按钮本身通过更改输入的值然后触发输入来避免竞争条件,这使得去抖动在键入输入和使用按钮时都是流畅的。
link: function(scope, element, attrs) {
element.bind('click', function() {
$timeout(function() {
var input = element.parent().find('input');
var changingTo = parseInt(input[0].value) + parseInt(scope.inc);
if(scope.inc < 0 || isNaN(changingTo)) {
var min = parseInt(input[0].min);
if(isNaN(changingTo)) {
changingTo = min;
} else if(changingTo < min) {
return;
}
} else {
var max = parseInt(input[0].max);
if(changingTo > max) {
return;
}
}
input[0].value = String(changingTo);
input.trigger('input');
});
});
}
答案 0 :(得分:4)
文档的答案是:https://code.angularjs.org/1.2.19/docs/api/ng/type/ngModel.NgModelController
您希望使用$viewChangeListeners
代替$watch
,因此根据debounce的工作方式,您可能需要推送到$formatters
:
ngModelCtrl.$viewChangeListeners.push(function(){
var val = parseInt(ngModelCtrl.$viewValue);
if(!isNaN(val)) {
...
}
});
虽然我还没有使用去抖动选项,所以我不知道这是否能解决您的问题,但这就是您观看viewValue的方式。
答案 1 :(得分:2)
如果标签具有ng-model和match属性,这将观察ngModelController的$ viewValue。也可以观察其他ngModelController $ viewValues,就像在具有许多输入指令的表单中一样。
(function () {
'use strict';
angular
.module('app.commons')
.directive('match', MatchValidator);
function MatchValidator() {
return {
require: 'ngModel',
link: LinkFunction
};
function LinkFunction(scope, element, attrs, ngModel) {
scope.$watch(function(){
return ngModel.$viewValue;
},
function(newValue, oldValue){
// do something
}
);
}
}
})();
答案 2 :(得分:2)
观看$ viewValue的另一种解决方案是允许无效的ng-model更新,然后你可以改为观看模型。
ng-model-options="{allowInvalid: true}"
请参阅:https://docs.angularjs.org/api/ng/directive/ngModelOptions
这不是这个问题的直接答案,但我认为它将有助于人们访问此主题的许多用例。
答案 3 :(得分:0)
就个人而言,我不得不使用$ formatters来避免等待去抖。