我有一个带ngModel
绑定的文本框,如下所示:
<input type="text" ng-model="typing" />
此texbox的值
value: {{ typing }}
我希望模型延迟在我输入时更新值。也许如果我停止输入500ms,模型将更新所有值(我在文本框中键入的所有内容)。 我做了一些谷歌,但没有运气。安永有什么想法?请帮忙。
修改
此Angularjs: input[text] ngChange fires while the value is changing并未为我的案例提供解决方案。它会在模糊后带来解决方案更新值,但我希望在停止输入后更新值,而不是模糊文本框。
编辑2(答案)
对于角度版本1.4,指令ngModelOptions
在我的情况下很有用。我可以这样编写<input ng-model="typing" ng-model-options="{ updateOn: 'default', debounce: {'default': 500, 'blur': 0} }" />
来将更新值延迟到默认模型500ms并在失去焦点时立即更新。
答案 0 :(得分:30)
处理此问题的最简单方法可能是编写一个包含<input>
元素的指令并添加延迟行为。这是我为同一目的而写的指令:
angular.module('MyModule')
.directive('easedInput', function($timeout) {
return {
restrict: 'E',
template: '<div><input class="{{externalClass}} my-eased-input" type="text" ng-model="currentInputValue" ng-change="update()" placeholder="{{placeholder}}"/></div>',
scope: {
value: '=',
timeout: '@',
placeholder: '@',
externalClass: '@class'
},
transclude: true,
link: function ($scope) {
$scope.timeout = parseInt($scope.timeout);
$scope.update = function () {
if ($scope.pendingPromise) { $timeout.cancel($scope.pendingPromise); }
$scope.pendingPromise = $timeout(function () {
$scope.value = $scope.currentInputValue;
}, $scope.timeout);
};
}
}
});
此指令将在您的HTML中调用,如下所示:
<eased-input value="myValue" timeout="500" placeholder="Please enter text..." />
解析指令:
该指令使用angular的$timeout
服务来处理时间:它是调用setTimeout
的可注入,可模拟,惯用的替代方法。此服务注入指令构造函数。
该指令接受三个属性:value
,timeout
和placeholder
。
此处的value
属性绑定到控制器范围内的变量,该控制器拥有封闭的“上下文”。在这种情况下,它绑定到myValue
,即绑定到此代码的任何控制器上的$scope.myValue
。它具有双向绑定,由指令的'='
属性中的scope
条目表示。这意味着当该指令更新value
时,更改将传播到拥有该指令的控制器;因此,$scope.myValue
将在指令内更改value
时更改。
timeout
和placeholder
属性具有单向绑定:指令从属性中读取它们的值,但不会更改它们。它们实际上是配置值。
指令上的template
属性显示了Angular编译并链接后将在其位置生成的HTML。它基本上只是一个input
元素,具有一些特殊且不那么特殊的属性。输入框中的值通过currentInputValue
绑定到指令$scope
上的ng-model
变量。输入框中的change
事件通过update
指令绑定到指令$scope
上的ng-change
函数。
该过程的核心在于指令的link
函数:我们定义了一个update
方法。如上所述,此方法绑定到指令的HTML模板中输入框的change
事件。因此,每次用户更改框中的输入时,都会调用update
。
此方法使用$timeout
服务。它告诉$timeout
服务等待timeout
毫秒,然后应用设置$scope.value = $scope.currentInputValue
的回调。这与调用setTimeout(function () {$scope.value = $scope.currentInputValue}, timeout)
类似。
$timeout
调用返回一个promise。我们可以通过调用p
取消等待执行的$timeout
生成的承诺$timeout.cancel(p)
。这就是update
在第一行中所做的事情:如果我们从之前的更改事件中得到承诺,我们会在创建新事件之前取消它。这意味着如果我们有例如500毫秒超时,更新被调用两次,相隔400毫秒的呼叫,我们只有一个承诺等待开火。
承诺在解决后设置$scope.value = currentInputValue
;即,它将“向外可见”value
属性设置为具有输入框内容的值。 value
只会改变 - 外部控制器只会在value
毫秒的静止期后看到timeout
更改,我相信这是您所追求的行为。
答案 1 :(得分:11)
如果您可以在模型中使用第二个属性,则可以将$scope.$watch
与debounce
函数一起使用:
<强> HTML 强>
<input type="text" ng-model="typing" />
<input type="text" value="{{ typed }}" />
<强>的Javascript 强>
$scope.$watch('typing', debounce(function() {
$scope.typed = $scope.typing;
$scope.$apply();
}, 500));
您可以编写自己的去抖功能,也可以使用现有功能。有一个很好的实现here,或者,如果你碰巧使用了unexcore.js,you're already set。
这是一个jsFiddle示例。
更新:Angular 1.3现在有一种内置的方式可以去除用户输入:ngModelOptions。