23

Can't seem to google up an example of how this is done.

I have successfully created a textbox that calls a function every time it changes. What I would like to do is only call the function when the user has stopped typing for x milliseconds.

I know how to do it in JQuery using the keyup event, and can probably make it work this way, but want to do it "the Angular Way".

Edit

Maybe it wasn't clear from the tag or text, but I am using AngularJS, and want to use correct methodology for that framework to create this delay functionality.

0

3 Answers 3

28

There is ng-model-options for this manner

<input id="delayedModel" ng-model="delayedModel" ng-change="callDelayed()" ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }" />

the callDelayed method only calls after 500 ms from typing the last char or on blur

Here is the documentation https://docs.angularjs.org/api/ng/directive/ngModelOptions

Sign up to request clarification or add additional context in comments.

1 Comment

Solved it in an instant. Should be the accepted answer
22

For angular approach can inject $timeout in controller as dependency and use $watch on scope variable you've assigned in ng-model.

var timer=false;
$scope.ModelName='foo';
$scope.$watch('ModelName', function(){
  if(timer){
      $timeout.cancel(timer)
  }  
  timer= $timeout(function(){
      /* run code*/
   },delay)
});

5 Comments

Thanks! I already had the watch bit and was injecting $timeout into my controller (but had no idea how to use it), so that fixed it in 30 seconds flat.
$timeout returns a promise... I had to look that part up in docs to figure out how to use cancel().
What happens if you dont cancel? Because its setTimeout not setInterval?
@Vury certainly need to cancel promise but not sure if timer=$timeout(... wouldn't do automatic cancel or not. Docs do say that cancel will trigger promise reject
I suggest to initialize the timer var to null instead of false. My IDE throws a warning with a boolean.
4

While @charlietfl provided totally acceptable answer I would like to share with you another approach without using $watch method:

Template:

<input id="delayedModel" ng-model="delayedModel" ng-change="callDelayed()"/>

Controller:

    (function (timer, delay) {
        $scope.callDelayed= function () {
            if(timer){
                $timeout.cancel(timer)
            }
            timer = $timeout(function(){

                /* run code*/

            }, delay)
        };
    })(false, 500);

Maybe it's worth to point out why self-executing anonymous function is used. The main reason is to not pollute controller scope with time and delay variables. In this case they are defined in local function scope.

[UPDATE]

I've also found an interesting AngularJS project called angular-debounce that makes it really easy to achieve same effect. Using debounce directive it's possible to dealy model update like this:

<input type="text" ng-model="delayedModel" debounce="500"></input>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.