Angular ng-change delay
Solution 1
AngularJS 1.3+
Since AngularJS 1.3 you can utilize the debounce
property ngModelOptions
provides to achieve that very easy without using $timeout
at all. Here's an example:
HTML:
<div ng-app='app' ng-controller='Ctrl'>
<input type='text' placeholder='Type a name..'
ng-model='vm.name'
ng-model-options='{ debounce: 1000 }'
ng-change='vm.greet()'
/>
<p ng-bind='vm.greeting'></p>
</div>
JS:
angular.module('app', [])
.controller('Ctrl', [
'$scope',
'$log',
function($scope, $log){
var vm = $scope.vm = {};
vm.name = '';
vm.greeting = '';
vm.greet = function greet(){
vm.greeting = vm.name ? 'Hey, ' + vm.name + '!' : '';
$log.info(vm.greeting);
};
}
]);
-- OR --
Before AngularJS 1.3
You'll have to use $timeout to add a delay and probably with the use of $timeout.cancel(previoustimeout) you can cancel any previous timeout and run the new one(helps to prevent the filtering to be executed multiple times consecutovely within a time interval)
Here is an example:
app.controller('MainCtrl', function($scope, $timeout) {
var _timeout;
//...
//...
$scope.FilterByName = function() {
if(_timeout) { // if there is already a timeout in process cancel it
$timeout.cancel(_timeout);
}
_timeout = $timeout(function() {
console.log('filtering');
_timeout = null;
}, 500);
}
});
Solution 2
You could use $timeout
to add a delay and probably with the use of $timeout.cancel(previoustimeout)
you can cancel any previous timeout and run the new one(helps to prevent the filtering to be executed multiple times consecutovely within a time interval)
Example:-
app.controller('MainCtrl', function($scope, $timeout) {
var _timeout;
//...
//...
$scope.FilterByName = function () {
if(_timeout){ //if there is already a timeout in process cancel it
$timeout.cancel(_timeout);
}
_timeout = $timeout(function(){
console.log('filtering');
_timeout = null;
},500);
}
});
Solution 3
I know the question is too old. But still want to provide one quicker way to achieve this using debouncing.
So the code can be written as
<input ng-model="xyz" ng-change="FilterByName()" ng-model-options="{debounce: 500}"/>
Debounce will take the number in milliseconds.
MGot90
Updated on November 02, 2020Comments
-
MGot90 over 3 years
I have an input which filters a ng-repeat list on change. The repeat contains a lot of data and takes a few seconds to filter through everything. I would like their to be 0.5 second delay before I start the filtering process. What is the correct way in angular to create this delay?
Input
<input ng-model="xyz" ng-change="FilterByName()" />
Repeat
<div ng-repeat"foo in bar"> <p>{{foo.bar}}</p> </div>
Filter Function
$scope.FilterByName = function () { //Filtering Stuff Here });
Thanks
-
Vincent Sels over 9 yearsNote that
ng-model-options
was only added in Angular v1.3 (and the debounce property in beta.8). Those who still need to use an older version of Angular will have to resort to other solutions, like the one from PSL, or by using an external module like ng-debounce. -
PSL almost 9 yearsTo the downvoter and future visitors: This answer was added for Angular 1.2.x, and added probably before 1.3.x was released which has the the debounce option with ng-model-options and never got a chance to revise the answer before a better answer from @rckd came in (around 3 months after this one).
-
SStanley over 8 yearsEven though I am using angular js 1.4 I still find the $timeout solution useful with
ng-change
when I don't want to debounce the model. -
Johan Baaij almost 8 yearsA downside could be that this seems to delay validations like ng-pattern as well.